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.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow