Как использовать транзакции в Django ORM

Ответ

Транзакции в 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), позволяя откатывать только часть операций.