Функция on_commit

Функция on_commit из модуля django.db.transaction позволяет зарегистрировать callback-функцию, которая будет выполнена только после успешной фиксации текущей транзакции. Это полезно для выполнения действий, которые должны произойти только после подтверждения изменений в базе данных, например, отправка уведомлений, очистка кеша или вызов внешних API. Если транзакция откатывается, зарегистрированные функции не вызываются.

Синтаксис

pythonfrom django.db import transaction

transaction.on_commit(callable, using=None)

Параметр callable - это функция или любой вызываемый объект, который будет выполнен после фиксации транзакции. Необязательный параметр using указывает псевдоним подключения к базе данных, для которого регистрируется обратный вызов.

Пример

Допустим, у нас есть модель статьи, и после сохранения новой статьи мы хотим отправить уведомление подписчикам, но только если статья действительно сохранена в базе данных:

pythonfrom django.db import models, transaction
from myapp.models import Article
from myapp.tasks import send_notification

with transaction.atomic():
  article = Article.objects.create(title="New Article", status="published")
  transaction.on_commit(lambda: send_notification(article.id))

В этом примере функция send_notification будет вызвана только после того, как транзакция успешно зафиксируется. Если произойдет ошибка до фиксации, уведомление не будет отправлено.

Пример

Рассмотрим ситуацию с несколькими вложенными транзакциями. Функция on_commit выполняется только после фиксации самой внешней транзакции:

pythonfrom django.db import transaction
from myapp.models import Article

def cleanup_cache():
  print("Cache cleared")

with transaction.atomic():
  with transaction.atomic():
    article = Article.objects.create(title="Draft Article")
    transaction.on_commit(cleanup_cache)
    # Функция будет выполнена только после
    # фиксации внешней транзакции

Несмотря на то, что on_commit вызван внутри вложенной транзакции, callback выполнится только после фиксации внешнего блока atomic.

Пример

Если вам нужно выполнить действие сразу, если транзакция уже зафиксирована, или отложить его, если транзакция активна, можно использовать проверку состояния:

pythonfrom django.db import transaction
from myapp.models import Category

def update_category_count():
  count = Category.objects.count()
  print(f"Total categories: {count}")

if transaction.get_connection().in_atomic_block:
  transaction.on_commit(update_category_count)
else:
  update_category_count()

В этом примере мы проверяем, находимся ли мы внутри транзакционного блока. Если да - регистрируем callback через on_commit, иначе выполняем функцию сразу.

Пример

on_commit также можно использовать с декоратором transaction.atomic для более компактной записи:

pythonfrom django.db import transaction
from myapp.models import Article
from myapp.services import index_article

@transaction.atomic
def create_article_and_index(title, content):
  article = Article.objects.create(title=title, content=content)
  transaction.on_commit(lambda: index_article(article.id))
  return article

Функция index_article, которая, например, добавляет статью в поисковый индекс, будет вызвана только после успешного завершения всей транзакции в декорируемой функции.

Пример

Если вам нужно зарегистрировать несколько callback-функций, они будут выполнены в порядке регистрации:

pythonfrom django.db import transaction
from myapp.models import Article

with transaction.atomic():
  article = Article.objects.create(title="Final Article")

  transaction.on_commit(lambda: print("First callback"))
  transaction.on_commit(lambda: print("Second callback"))
  transaction.on_commit(lambda: print("Third callback"))

Результат выполнения кода:

python"First callback"
"Second callback"
"Third callback"

Смотрите также

  • функция atomic,
    которая обеспечивает атомарность операций с базой данных
  • метод save,
    который сохраняет объект модели в базу данных
  • метод delete,
    который удаляет объект модели из базы данных
  • сигнал post_save,
    который отправляется после сохранения модели