What are Django Signals?
Django Signals are a dispatch mechanism that allows decoupled applications to get notified when certain actions occur elsewhere in the framework. When an action happens (a "sender" sends a signal), any registered function (a "receiver") can listen for that signal and execute its own code without the sender needing to know anything about the receiver.
-
Sender: The component that dispatches the signal (e.g., a Django model, a view function, or Django itself).
-
Signal: The instance that connects senders and receivers (e.g.,
pre_save,post_delete,request_finished). -
Receiver (or Handler): A function that executes when the signal is sent.
Common Built-in Signals
Django provides several built-in signals, which are often used with models.
| Signal Name | Description | When is it Sent? |
pre_save |
Sent before a model's save() method is called. |
Before saving an object. |
post_save |
Sent after a model's save() method is called. |
After an object is saved (created or updated). |
pre_delete |
Sent before a model's delete() method is called. |
Before an object is deleted. |
post_delete |
Sent after a model's delete() method is called. |
After an object is deleted. |
m2m_changed |
Sent when a ManyToManyField is changed. |
When a many-to-many relationship is updated. |
request_finished |
Sent when Django finishes rendering a HTTP request. | After every request is processed. |
Practical Implementation
For this, we will implement this on our existing project.
1. Create signals.py inside users app.
Add the signal receiver:
from django.apps import AppConfig
class UsersConfig(AppConfig):
name = 'users'
def ready(self):
import users.signals
2. Create your signals users/signals.py
import the following to the signals.py file
from django.db.models.signals import pre_save, post_save, pre_delete, post_delete, m2m_changed
from django.dispatch import receiver
from users.model import CustomUser
3.1 pre_save – Before User is Saved
@receiver(pre_save, sender=CustomUser)
def user_pre_save(sender, instance, **kwargs):
print(f"[PRE_SAVE] User about to be saved: {instance.username}")
3.2 post_save – After User is Saved
@receiver(post_save, sender=CustomUser)
def user_post_save(sender, instance, created, **kwargs):
if created:
print(f"[POST_SAVE] New user created: {instance.username}")
else:
print(f"[POST_SAVE] User updated: {instance.username}")
3.3 pre_delete – Before User is Deleted
@receiver(pre_delete, sender=CustomUser)
def user_pre_delete(sender, instance, **kwargs):
print(f"[PRE_DELETE] User about to be deleted: {instance.username}")
3.4 post_delete – After User is Deleted
@receiver(post_delete, sender=CustomUser)
def user_post_delete(sender, instance, **kwargs):
print(f"[POST_DELETE] User deleted: {instance.username}")