rsinger86/django-lifecycle

Cascade delete not firing BEFORE/AFTER_DELETE hooks?

ognjenk opened this issue · 3 comments

Hi,
I have 2 models:

class Model_A(LifecycleModelMixin, models.Model):
    code = models.CharField(max_length=50)

class Model_B(LifecycleModelMixin, models.Model):
    code = models.CharField(max_length=50)
    model_a = models.ForeignKey(to="app.Model_A", on_delete=models.CASCADE, blank=True, null=True)

    @hook(AFTER_DELETE)
    def do_after_delete(self):
        print("AFTER_DELETE")

    @hook(BEFORE_DELETE)
    def do_before_delete(self):
        print("BEFORE_DELETE")

It seems like lifecycle hooks are not triggered when I delete one instance of Model_A which has a couple of Model_B children.
Hooks are normally triggered when I delete Model_B directly.

I am not doing SQL delete, rather I am triggering django instance delete by doing:

instance_a = Model_A.objects.get(code="ABC)
instance_a.delete()

My understanding is that this should fire delete signals, so I was expecting they would fire on cascade deleted instances as well.
Is this expected behaviour or am I doing something wrong?

Thanks in advance!

vik-y commented

Was thinking of using this library in one of my projects. This one seems to be a major problem. Did you figure it out yet?

This seems like expected behavior IMO. From the Django documentation:

Note that the delete() method for an object is not necessarily called when deleting objects in bulk using a QuerySet or as a result of a cascading delete. To ensure customized delete logic gets executed, you can use pre_delete and/or post_delete signals.

I wouldn't expect this library to automatically hook up a post_delete signal since its stated purpose is just to automate clunky manual overrides to model .save() / .delete() methods. But maybe the *_DELETE hooks should have some additional documentation explaining this limitation.

As @dmartin said, Django itself doesn't call .delete() neither it fires related django signals, so we can't provide a general enough solution that works for everyone.

As a workaround you could add a hook on your Model_A that calls your Model_B hooks.

I'm closing this issue. Feel free to reopen it if it's needed.