Django Signals

Oct 24, 2014

Django allows sending of notifications between decoupled applications through signals. The signaling in django is actually an implementation of the publish-subscribe pattern.

A common use case is to perform some processing on an object before committing it to the database. The processing can be related to data clean up, indexing, or calculating the value of a derived attribute. The django.db.models.signals.pre_save signal should be used for this.

Another possible use case is to update another object after committing this object in to the database, e.g. mark the previous log as 'stale' in a log table. The signal to connect to in this case is django.db.models.signals.post_save. WARNING: connecting to pre_save in this case can get us in trouble.

Django has a set of built-in signals which are emitted whenever the respective event takes place. Our desired action upon receiving a signal needs to be coded as a function, let's call it the receiver function.

def my_receiver(sender, **kwargs):
    print("I have received a signal")

Say, we want to connect the receiver function with django.db.models.signals.post_save signal. There are two ways of acheiving this.

# 1. Calling connnect on the signal
from django.db.models.signals import post_save

post_save.connect(my_receiver) 

# 2. Using the receiver decorator
from django.dispatch import receiver

@receiver(post_save)
def my_receiver(sender, **kwargs):
        print("I have recieved a signal")

Also, if you want to target a specific model then supply the model argument.

@receiver(post_save, sender=MyModel)
def my_receiver(sender, **kwargs):
        print("I have recieved a signal from MyModel")