Buscar..


Transacciones atómicas

Problema

Por defecto, Django confirma inmediatamente los cambios en la base de datos. Cuando se producen excepciones durante una serie de confirmaciones, esto puede dejar su base de datos en un estado no deseado:

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

En el siguiente escenario:

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

Se produce una excepción al intentar agregar el producto de pantalón a la categoría de ropa. En este punto, la categoría en sí ya se ha agregado, y el producto de la camisa se ha agregado a ella.

La categoría incompleta y el producto que contiene deberían eliminarse manualmente antes de corregir el código y llamar al método create_category() una vez más, ya que de lo contrario se crearía una categoría duplicada.


Solución

El módulo django.db.transaction permite combinar múltiples cambios de base de datos en una transacción atómica :

[una] serie de operaciones de base de datos de manera que ocurran todas o no ocurra nada.

Aplicado al escenario anterior, esto se puede aplicar como decorador :

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)

O utilizando un administrador de contexto :

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)

Ahora, si se produce una excepción en cualquier etapa de la transacción, no se confirmarán cambios en la base de datos.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow