Django
Транзакции базы данных
Поиск…
Атомные транзакции
проблема
По умолчанию Django немедленно вносит изменения в базу данных. Когда исключения происходят во время серии коммитов, это может оставить вашу базу данных в нежелательном состоянии:
def create_category(name, products):
category = Category.objects.create(name=name)
product_api.add_products_to_category(category, products)
activate_category(category)
В следующем сценарии:
>>> create_category('clothing', ['shirt', 'trousers', 'tie'])
---------------------------------------------------------------------------
ValueError: Product 'trousers' already exists
Исключение возникает при попытке добавить продукт брюк в категорию одежды. К этому моменту уже добавлена сама категория, и к ней добавлен продукт рубашки.
Неполную категорию и содержащий продукт нужно удалить вручную до исправления кода и вызова create_category()
еще раз, так как в противном случае будет создана повторяющаяся категория.
Решение
Модуль django.db.transaction
позволяет объединять несколько изменений базы данных в атомную транзакцию :
[a] ряд операций с базой данных, в которых либо все происходит, либо ничего не происходит.
Применительно к описанному выше сценарию это можно применить в качестве декоратора :
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)
Или с помощью диспетчера контекстов :
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)
Теперь, если исключение происходит на любом этапе транзакции, никаких изменений базы данных не будет.