Django
Databasetransacties
Zoeken…
Atoomtransacties
Probleem
Standaard maakt Django onmiddellijk wijzigingen door in de database. Wanneer uitzonderingen optreden tijdens een reeks vastleggingen, kan uw database in een ongewenste staat achterblijven:
def create_category(name, products):
category = Category.objects.create(name=name)
product_api.add_products_to_category(category, products)
activate_category(category)
In het volgende scenario:
>>> create_category('clothing', ['shirt', 'trousers', 'tie'])
---------------------------------------------------------------------------
ValueError: Product 'trousers' already exists
Een uitzondering doet zich voor wanneer wordt geprobeerd het broekproduct aan de kledingcategorie toe te voegen. Op dit punt is de categorie zelf al toegevoegd en is het shirtproduct eraan toegevoegd.
De onvolledige categorie en het product moeten handmatig worden verwijderd voordat de code wordt create_category()
en de methode create_category()
wordt create_category()
, omdat anders een dubbele categorie wordt gemaakt.
Oplossing
Met de django.db.transaction
module kunt u meerdere databasewijzigingen combineren in een atomaire transactie :
[a] reeks databasebewerkingen zodat ze allemaal voorkomen, of er gebeurt niets.
Toegepast op het bovenstaande scenario, kan dit worden toegepast als decorateur :
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)
Of door een contextmanager te gebruiken :
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)
Als er nu een uitzondering optreedt in een bepaald stadium van de transactie, worden er geen databasewijzigingen doorgevoerd.