Hi all, There's a discussion ongoing on ticket #18094 (https://code.djangoproject.com/ticket/18094) that has enough potential back-compat implications that it seems worth getting feedback here.
Currently, when you delete a concrete-inheritance child model instance, pre_delete and post_delete signals are sent both for the child and parent models. In contrast, when you delete a proxy model instance, the pre/post_delete signals are sent only for the proxy model class, never for the parent concrete class. This is problematic. Imagine a reusable tagging app that has a Tag model, and attaches a pre_delete signal handler for Tag instances. In my usage of that app, I use my own TagProxy subclass. When I delete a TagProxy instance, a Tag is in fact deleted, but the app's pre_delete signal handler never fires. This violates the reasonable assumption that subclassing doesn't change superclass behavior except where it explicitly overrides it. So we'd like to make the obvious fix, which is to fire the pre/post_delete signals for every superclass of the instance(s) you delete, regardless of whether they are parents via concrete or proxy inheritance. This raises the question of consistency with pre/post_save and pre/post_init, which are currently both sent only once, for the exact class being saved/initialized (thus already inconsistent with delete signals, which are also sent for concrete-inheritance parents). The same Tag scenario above would apply equally to save and init signals: the tagging app should be able to assume that if it registers a save or init signal handler for Tag, it will get called whenever a Tag is saved or initialized, even if that's happening via a Tag subclass. So it seems that perhaps we should also fix the save and init signals to be fired for each superclass. Is this an acceptable change from a backwards-compatibility perspective? In the common case of registering a signal handler using "sender=", it should be a clear win: signal handlers will now execute when you'd expect them to. But in the case of, say, a generic audit-trail handler that listens for all post_save (no sender specified), it will now get what could seem like duplicate signals for inherited models (one for each superclass of the instance being saved). Thoughts? (The other approach that might come to mind for fixing this would be to move the fix into the signals framework itself, so that it executes signal handlers registered for signal=Foo anytime a signal is fired for anything that passes issubclass(Foo), rather than requiring Foo identity. This is appealing, and would solve the potential "duplicate signals" problem with a generic receiver, but is a much more invasive change in the fundamental semantics of the signals framework, so I don't think it's a realistic option.) Carl
signature.asc
Description: OpenPGP digital signature