Django
Transacciones de base de datos
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.