Django Transactions atomiques


Exemple

Problème

Par défaut, Django valide immédiatement les modifications apportées à la base de données. Lorsque des exceptions se produisent pendant une série de validations, cela peut laisser votre base de données dans un état indésirable:

def create_category(name, products):
    category = Category.objects.create(name=name)
    product_api.add_products_to_category(category, products)
    activate_category(category)

Dans le scénario suivant:

>>> create_category('clothing', ['shirt', 'trousers', 'tie'])
---------------------------------------------------------------------------
ValueError: Product 'trousers' already exists

Une exception se produit lors de la tentative d’ajout du produit pantalon à la catégorie des vêtements. À ce stade, la catégorie elle-même a déjà été ajoutée et le produit de la chemise a été ajouté.

La catégorie incomplète et le produit contenant doivent être supprimés manuellement avant de corriger le code et d'appeler à nouveau la méthode create_category() , sinon une catégorie de doublons serait créée.


Solution

Le module django.db.transaction vous permet de combiner plusieurs modifications de base de données en une transaction atomique :

[une] série d'opérations de base de données telles que toutes se produisent ou rien ne se produit.

Appliqué au scénario ci-dessus, il peut être appliqué en tant que décorateur :

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)

Ou en utilisant un gestionnaire de contexte :

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)

Maintenant, si une exception se produit à n'importe quelle étape de la transaction, aucune modification de base de données ne sera validée.