Вызывается ли сигнал post_save в Django внутри транзакции базы данных

Ответ

Да, сигнал post_save вызывается внутри транзакции, которая оборачивает операцию сохранения модели.

Это означает, что сигнал срабатывает после успешного выполнения SQL-запроса INSERT или UPDATE, но до выполнения COMMIT для всей транзакции.

Ключевые следствия:

  1. Откат изменений: Если после срабатывания сигнала в том же блоке кода (например, в view) произойдет исключение, вся транзакция будет отменена. Это включает как сохранение самой модели, так и любые изменения в БД, сделанные в обработчике сигнала.
  2. Недоступность данных: Другие процессы или запросы не увидят изменения в базе данных, пока транзакция не будет закоммичена.

Для выполнения действий, которые должны произойти только после успешного завершения транзакции (например, запуск задачи в Celery или отправка уведомления), следует использовать transaction.on_commit().

Пример:

from django.db import transaction
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import MyModel

# Этот обработчик выполняется ВНУТРИ транзакции
@receiver(post_save, sender=MyModel)
def my_signal_handler(sender, instance, created, **kwargs):
    if created:
        print(f"Объект {instance.pk} создан, но транзакция еще не закоммичена.")

        # Эта задача запустится только ПОСЛЕ успешного COMMIT
        transaction.on_commit(
            lambda: some_celery_task.delay(instance.pk)
        )