Что делает функция transaction.on_commit в Django и когда ее следует использовать

Ответ

Функция transaction.on_commit() в Django позволяет зарегистрировать колбэк (функцию), который будет выполнен только после успешного завершения (коммита) текущей транзакции в базе данных.

Это критически важно для выполнения действий, которые не должны происходить, если транзакция откатится. Основной сценарий использования — запуск фоновых задач, отправка уведомлений или вызов внешних API.

Почему это важно?

Представьте, что вы отправляете приветственное письмо сразу после создания пользователя. Если после отправки письма в транзакции произойдет ошибка и создание пользователя откатится, пользователь получит письмо, хотя его аккаунт не существует. on_commit решает эту проблему.

Пример:

from django.db import transaction
from .tasks import send_welcome_email

def create_user_and_send_email(username, email):
    # Начало транзакции (неявно, если ATOMIC_REQUESTS=True, или явно)
    user = User.objects.create(username=username, email=email)

    # Регистрируем задачу, которая выполнится только после коммита
    transaction.on_commit(lambda: send_welcome_email.delay(user.id))

    # ... другие операции в рамках транзакции
    # Если здесь произойдет ошибка, on_commit() не будет вызван.

Ключевые особенности:

  • Гарантия выполнения: Код выполняется только если транзакция успешно зафиксирована в БД.
  • Изоляция: Позволяет отделить логику работы с БД от побочных эффектов (side effects).
  • Тестирование: Для корректной работы в тестах требует использования django.test.TestCase, который оборачивает каждый тест в транзакцию.