Django
Transakcje w bazie danych
Szukaj…
Transakcje atomowe
Problem
Domyślnie Django natychmiast wprowadza zmiany w bazie danych. Gdy wystąpią wyjątki podczas serii zatwierdzeń, może to spowodować pozostawienie bazy danych w niechcianym stanie:
def create_category(name, products):
category = Category.objects.create(name=name)
product_api.add_products_to_category(category, products)
activate_category(category)
W następującym scenariuszu:
>>> create_category('clothing', ['shirt', 'trousers', 'tie'])
---------------------------------------------------------------------------
ValueError: Product 'trousers' already exists
Wyjątek stanowi próba dodania produktu do spodni do kategorii odzieży. W tym momencie sama kategoria została już dodana, a produkt koszulowy został do niej dodany.
Niekompletna kategoria i zawierający produkt musiałaby zostać ręcznie usunięta przed create_category()
kodu i wywołaniem metody create_category()
jeszcze raz, w przeciwnym razie utworzono by zduplikowaną kategorię.
Rozwiązanie
Moduł django.db.transaction
pozwala łączyć wiele zmian w bazie danych w transakcję atomową :
[a] seria operacji na bazach danych, które albo wszystkie występują, albo nic się nie dzieje.
W przypadku powyższego scenariusza można to zastosować jako dekorator :
from django.db import transaction
@transaction.atomic
def create_category(name, products):
category = Category.objects.create(name=name)
product_api.add_products_to_category(category, products)
activate_category(category)
Lub za pomocą menedżera kontekstu :
def create_category(name, products):
with transaction.atomic():
category = Category.objects.create(name=name)
product_api.add_products_to_category(category, products)
activate_category(category)
Teraz, jeśli na jakimkolwiek etapie transakcji wystąpi wyjątek, zmiany w bazie danych nie zostaną zatwierdzone.