Ответ
Да, сигнал post_save
вызывается внутри транзакции, которая оборачивает операцию сохранения модели.
Это означает, что сигнал срабатывает после успешного выполнения SQL-запроса INSERT
или UPDATE
, но до выполнения COMMIT
для всей транзакции.
Ключевые следствия:
- Откат изменений: Если после срабатывания сигнала в том же блоке кода (например, в view) произойдет исключение, вся транзакция будет отменена. Это включает как сохранение самой модели, так и любые изменения в БД, сделанные в обработчике сигнала.
- Недоступность данных: Другие процессы или запросы не увидят изменения в базе данных, пока транзакция не будет закоммичена.
Для выполнения действий, которые должны произойти только после успешного завершения транзакции (например, запуск задачи в 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)
)