1

I have models like this:

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()

I also have a signal like this:

@receiver(post_delete, sender=Child)
def handle_delete_child(sender, instance, **kwargs):
  log = Log(parent = instance.parent, detail="child deleted")
  log.save()

Now, if I try to delete the parent, I can see with debug on that the steps are going like this:

  1. Delete parent's logs.
  2. Delete parent's children (causing new log to be written as per the signal).
  3. Try to delete parent, but fails with "Cannot delete or update a parent row: a foreign key constraint fails", I think on the log created in step 2.

If I was able to specify that #2 should happen before #1, I think that would solve the problem, but I cannot find any reference to such things in the docs. Even a creative solution like a new signal or a model method override would be welcome.

Pouya Esmaeili
  • 1,265
  • 4
  • 11
  • 25
Willow
  • 1,132
  • 5
  • 20

1 Answers1

1

Thanks to @Anentropic's comment and this question django temporarily disable signals I was able to come up with this solution. I didn't have to change any of the existing code from my question.

@receiver(signals.pre_delete, sender=Parent)
def handle_delete_project(sender, instance, **kwargs):
    signals.post_delete.disconnect(handle_delete_child, sender=Child)


@receiver(signals.post_delete, sender=Parent)
def handle_delete_project(sender, instance, **kwargs):
    signals.post_delete.connect(handle_delete_child, sender=Child)

Before that I tried doing this in the Parent.delete method, but that doesn't get called if you're bulk deleting in the Django admin.

Willow
  • 1,132
  • 5
  • 20