Django Inheriting Signals on Extended Models


Example

Django's signals are restricted to precise class signatures upon registration, and thus subclassed models are not immediately registered onto the same signal.

Take this model and signal for example

class Event(models.Model):
    user = models.ForeignKey(User)


class StatusChange(Event):
    ...


class Comment(Event):
    ...


def send_activity_notification(sender, instance: Event, raw: bool, **kwargs):
    """
    Fire a notification upon saving an event
    """

    if not raw:
        msg_factory = MessageFactory(instance.id)
        msg_factory.on_activity(str(instance))
post_save.connect(send_activity_notification, Event)

With extended models, you must manually attach the signal onto each subclass else they won't be effected.

post_save.connect(send_activity_notification, StatusChange)
post_save.connect(send_activity_notification, Comment)

With Python 3.6, you can leverage some additional class methods build into classes to automate this binding.

class Event(models.Model):

    @classmethod
    def __init_subclass__(cls, **kwargs):
        super().__init_subclass__(**kwargs)
        post_save.connect(send_activity_notification, cls)