Uważam, że potrzebujesz oddzielnego połączenia db, aby uzyskać oddzielną, jednoczesną transakcję. Jestem również całkiem pewien, że django zarządza tylko jednym połączeniem na bazę danych. Ale możesz stworzyć inny. Może istnieć dobry powód, aby tego nie robić. Na myśl przychodzi złożoność.
Myślę, że coś takiego by zadziałało:
from django.conf import settings
from django.db.utils import ConnectionHandler
def my_view(request):
"""Flirt with complexity by using two connections to db"""
private_connections = ConnectionHandler(settings.DATABASES)
db = router.db_for_write(model)
new_conn = private_connections[db]
new_conn.enter_transaction_management()
new_conn.managed(True)
new_cur = new_conn.cursor()
new_cur.execute("INSERT INTO ...")
new_conn.commit()
new_conn.close()
Pamiętaj, że nie możesz użyć django.db.transaction
ponieważ działa na globalnych instancjach połączeń w django.db.connections
, ale w każdym razie jest to tylko cienkie opakowanie wokół metod zarządzania transakcjami w obiekcie połączenia.
Myślę, że prawdziwe pytanie brzmi:dlaczego chcesz to zrobić?! A co jest złego w odpowiedzi Lakshmana Prasada? Możesz zatwierdzić/wycofać, kiedy tylko chcesz, więc nic nie stoi na przeszkodzie, aby wykonywać różne zadania w różnych transakcjach w jednym widoku. Fakt, że transakcje muszą być równoległe, a nie następujące po sobie, wskazuje na jakiś logiczny związek między nimi, co moim zdaniem wskazywałoby, że powinny one rzeczywiście być w tej samej transakcji.
Jeśli z drugiej strony próbujesz emulować jakiś rodzaj przetwarzania offline, którego powodzenie lub niepowodzenie w ogóle nie jest szczególnie istotne dla widoku, rozważ skonfigurowanie kolejki wiadomości i wykonanie tych wstawek w osobnym proces. selery jest popularnym pakietem, który właśnie to robi. Jeśli jednak czas odpowiedzi nie jest głównym problemem, nadal uważam, że kolejne transakcje powinny wystarczyć.
Aktualizacja:
Jeśli chcesz, aby pamięć podręczna oparta na bazie danych działała w trybie automatycznego zatwierdzania, a jednocześnie nadal uruchamiała logikę biznesową w pojedynczej (oddzielnej) transakcji, istnieje sposób django. Wszystko, co musisz zrobić, to upewnić się, że buforowanie odbywa się na zewnątrz commit_on_success
:
-
Jeśli używasz tylko oprogramowania pośredniczącego do buforowania, upewnij się, że znajduje się ono poza
TransactionMiddleware
. -
Jeśli używasz dekoratorów widoku pamięci podręcznej, zaryzykowałbym zgadnięcie, że możesz wyłączyć
TransactionMiddleware
(lub umieść widok problemu wautocommit
dekorator) i użyjcommit_on_success
dekorator wewnątrz dekorator pamięci podręcznej. Wygląda śmiesznie, ale nie wiem, dlaczego by nie zadziałało:@transaction.autocommit @cache_page(500) @transaction.commit_on_success def my_view(request): "..."
-
Jeśli używasz buforowania szablonów lub wykonujesz bardziej skomplikowane buforowanie ręczne, możesz również wyłączyć
TransactionMiddleware
(lub umieść widok problemu wautocommit
dekorator) i użyjcommit_on_success
jako menedżer kontekstu, aby umieścić tylko potrzebny kod w zarządzanej transakcji, pozostawiając resztę widoku w trybie automatycznego zatwierdzania.@transaction.autocommit def my_view(request): data = cache.get(some_key) with transaction.commit_on_success(): context = do_some_processing(data) cache.set(some_key, context['data']) return render('template/with/cache/blocks.html', context=context)