Лучшая практика создания записи модели в сигнале `post_save` при сохранении целостности данных в Django

Я работаю над приложением Django, где мне нужно автоматически создавать запись Setting со значениями по умолчанию каждый раз, когда создается новая запись User. Моя текущая реализация использует сигнал post_save модели User для обработки этой логики.

from django.db.models.signals import post_save
from django.db import transaction
from django.contrib.auth.models import User
from myapp.models import Setting

@receiver(post_save, sender=User)
def create_default_setting(sender, instance, created, **kwargs):
    if created:
        transaction.on_commit(lambda: Setting.objects.create(user=instance))

Я использовал transaction.on_commit, чтобы убедиться, что создание Setting записи происходит только после того, как транзакция создания User зафиксирована , чтобы избежать проблем, когда экземпляр User может еще не существовать в базе данных. Однако это отделяет создание Setting от транзакции создания User. Если по какой-либо причине создание Setting не удастся (например, ошибки валидации, проблемы с базой данных), то в итоге я получу запись User без соответствующей Setting, что нарушит целостность данных.

С другой стороны, если я не использую transaction.on_commit и создаю Setting непосредственно в сигнале post_save, есть риск попытаться создать запись Setting до того, как экземпляр User будет полностью сохранен в базе данных, или создать Setting даже тогда, когда создание User завершится неудачей из-за незафиксированной или откаченной транзакции.

Таким образом, у меня остается два несовершенных решения:

  1. Используя transaction.on_commit: Обеспечивает фиксацию User до создания Setting, но рискует получить неполные данные в случае неудачи при создании Setting.
  2. Без transaction.on_commit: Риск попытки создать Setting до того, как User будет полностью сохранен, или создания ненужных Setting записей в неудачных транзакциях.

Мои вопросы:

  1. Какова наилучшая практика работы с такими сценариями в Django, когда запись одной модели зависит от успешного создания записи другой модели?

  2. Есть ли способ обеспечить, чтобы записи User и Setting создавались в рамках одной транзакции, чтобы гарантировать целостность данных, избегая условий гонки или преждевременных запросов?

Любые рекомендации или предложения будут высоко оценены. Спасибо!

Вы можете создать Setting без использования transaction.on_commit. Это гарантирует, что в случае сбоя основной транзакции вся транзакция, включая все записи, созданные в сигналах и в методе save вашей модели, будет откачена.

Вернуться на верх