Ответ
Транзакции в Django ORM обеспечивают атомарность операций с базой данных, гарантируя, что группа запросов будет выполнена целиком или не выполнена вовсе. Это критически важно для поддержания целостности данных.
По умолчанию Django работает в режиме autocommit
, где каждый ORM-запрос выполняется в своей собственной транзакции. Для группировки нескольких операций в одну транзакцию используются следующие подходы:
1. Декоратор transaction.atomic
Самый простой способ обернуть всю функцию или метод в одну транзакцию. При возникновении исключения все изменения внутри функции будут автоматически отменены.
from django.db import transaction, IntegrityError
@transaction.atomic
def create_user_with_profile(username, first_name):
user = User.objects.create(username=username)
# Если здесь произойдет ошибка (например, IntegrityError),
# создание пользователя также будет отменено.
UserProfile.objects.create(user=user, first_name=first_name)
2. Контекстный менеджер transaction.atomic
Позволяет обернуть в транзакцию только определённый блок кода, а не всю функцию. Это даёт больше гибкости.
from django.db import transaction
def update_balance():
try:
with transaction.atomic():
# Блок кода, который должен быть атомарным
account_from = Account.objects.select_for_update().get(id=1)
account_to = Account.objects.select_for_update().get(id=2)
account_from.balance -= 100
account_to.balance += 100
account_from.save()
account_to.save()
except Account.DoesNotExist:
# Обработка ошибки, транзакция уже отменена
print("Счет не найден.")
Ключевые моменты:
@transaction.atomic
иwith transaction.atomic()
— основные и предпочтительные способы управления транзакциями.select_for_update()
используется для пессимистичной блокировки строк на время транзакции, чтобы предотвратить их изменение другими процессами.- Вложенные блоки
atomic
создают точки сохранения (savepoints), позволяя откатывать только часть операций.