Django Signal
The Django Signals is a strategy to allow decoupled applications to get notified
when certain events occur.
There are two key elements in the signals machinery: the senders
and the receivers
As the name suggests, the sender
is the one responsible to dispatch a signal,
and the receiver
is the one who will receive this signal and then do something.
- A receiver must be a function or an instance method which is to receive signals.
- A sender must either be a Python object, or None to receive events from any sender.
Types of Signal
Model signals
- The
django.db.models.signals
module defines a set of signals sent by the model system. - pre_save, post_save,
- pre_delete, post_delete
- m2m_changed
- request_started, request_finished
Management signals
- Signals sent by django-admin.
Request/response signals
- Signals sent by the core framework when processing a HTTP request.
Test signals
- Signals only sent when running tests.
Database Wrappers
- Signals sent by the database wrapper when a database connection is initiated.
Working
- To receive a signal, you need to
register a receiver
function that gets called when thesignal is sent
by using the Signal.connect() method. - There are two ways you can connect a receiver to a signal
Signal.connect()
@receiver()
- It internally use Signal.connect()
Without signal.py
- blog/models.py
- Here sender & receiver are at same place
- “sender=Fruit” —> will send signal only for Fruit model
- If not specified, will send signal for all models
# Way1 - signal.connect()
from django.db.models.signals import post_save
from django.contrib.auth.models import User
# receiver
def save_post(sender, instance, **kwargs):
print('something')
# sender
post_save.connect(save_post, sender=User)
- OR
# Way2 - @receiver()
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth.models import User
@receiver(post_save, sender=User)
def save_post(sender, instance, **kwargs):
print('something')
With signal.py
# signal.py
from django.contrib.auth.models import User
from django.db.models.signals import post_save, pre_save
from django.dispatch import receiver
# Way1 - signal.connect()
def save_pre(sender, instance, **kwargs):
print('Pre save --- something')
pre_save.connect(save_pre, sender=Fruit)
# Way2 - @receiver()
@receiver(post_save, sender=User)
def save_post(sender, instance, **kwargs):
print('Post save --- DO something')
- NOTE: Below code tells project about signal.py
# apps.py
from django.apps import AppConfig
class BlogConfig(AppConfig):
name = 'blog'
def ready(self):
import blog.signals
Custom signals
- Your applications can take advantage of the signal infrastructure and provide its own signals.
- Creating custom signal using
dispatch.Signal
- All signals are django.dispatch.Signal instances.
import django.dispatch
# Create Signal
pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])
class PizzaStore:
...
def send_pizza(self, toppings, size):
# Send Signal
pizza_done.send(sender=self.__class__, toppings=toppings, size=size)
...
# Receive Signal
@receiver(pizza_done)
def pizza_done_receiver(sender, **kwargs):
print(kwargs)
signals.py
from django.db.models.signals import post_save, pre_save
from django.dispatch import receiver