Могу ли я контролировать порядок каскадных удалений в Django?
У меня есть такие модели:
class Parent(models.Model):
pass
class Child(models.Model):
parent = models.ForeignKey(Parent, on_delete=models.CASCADE)
class Log(models.Model):
parent = models.ForeignKey(Parent, on_delete=models.CASCADE)
detail = models.TextField()
У меня также есть сигнал, подобный этому:
@receiver(post_delete, sender=Child)
def handle_delete_child(sender, instance, **kwargs):
log = Log(parent = instance.parent, detail="child deleted")
log.save()
Теперь, если я попытаюсь удалить родителя, я могу видеть с включенной отладкой, что шаги происходят следующим образом:
- Удаление журналов родителя.
- Удалите дочерние записи родителя (вызывая запись нового журнала в соответствии с сигналом).
- Попытайтесь удалить родителя, но происходит сбой с сообщением "Cannot delete or update a parent row: a foreign key constraint fails", я думаю, на логе, созданном в шаге 2.
Если бы я мог указать, что #2 должен произойти до #1, я думаю, это решило бы проблему, но я не могу найти никаких ссылок на такие вещи в документации. Даже креативное решение вроде нового сигнала или переопределения метода модели будет приветствоваться.
Благодаря комментарию @Pouya и этому вопросу django temporarily disable signals я смог прийти к этому решению. Мне не пришлось изменять никакой существующий код из моего вопроса.
@receiver(signals.pre_delete, sender=Parent)
def handle_delete_project(sender, instance, **kwargs):
signals.post_delete.disconnect(handle_delete_calendar_item, sender=Child)
@receiver(signals.post_delete, sender=Parent)
def handle_delete_project(sender, instance, **kwargs):
signals.post_delete.connect(handle_delete_calendar_item, sender=Child)
До этого я пробовал делать это в методе Parent.delete
, но он не вызывается, если вы удаляете массово в админке Django.