0
0
DjangoHow-ToBeginner · 4 min read

How to Use the receiver Decorator in Django Signals

In Django, use the @receiver decorator to connect a function to a signal easily by specifying the signal and optionally the sender. This decorator helps you write clean, readable code for handling events like model saves or deletes.
📐

Syntax

The @receiver decorator connects a function to a Django signal. You specify the signal to listen for and optionally the sender (the model or class sending the signal). The decorated function will run when the signal is sent.

  • @receiver(signal, sender=SenderClass): Decorates the handler function.
  • signal: The Django signal to listen to (e.g., post_save).
  • sender: Optional. Limits the signal to a specific sender.
  • The decorated function receives sender, instance, and other keyword arguments.
python
from django.dispatch import receiver
from django.db.models.signals import post_save
from myapp.models import MyModel

@receiver(post_save, sender=MyModel)
def my_handler(sender, instance, created, **kwargs):
    if created:
        print(f"New instance of {sender.__name__} created: {instance}")
💻

Example

This example shows how to use the @receiver decorator to print a message whenever a new Book model instance is created.

python
from django.db import models
from django.dispatch import receiver
from django.db.models.signals import post_save

class Book(models.Model):
    title = models.CharField(max_length=100)

@receiver(post_save, sender=Book)
def announce_new_book(sender, instance, created, **kwargs):
    if created:
        print(f"A new book titled '{instance.title}' was added.")
Output
A new book titled 'Django Basics' was added.
⚠️

Common Pitfalls

  • Forgetting to import the receiver decorator or the signal you want to use.
  • Not specifying the sender when you want to limit the signal to a specific model, causing the handler to run for all senders.
  • Defining the signal handler function without the correct parameters (sender, instance, and **kwargs).
  • Placing signal handlers in files that are not imported on startup, so the signals never connect.
python
from django.dispatch import receiver
from django.db.models.signals import post_save
from myapp.models import MyModel

# Wrong: Missing sender, runs for all models
@receiver(post_save)
def handler(sender, instance, **kwargs):
    print("Signal received")

# Right: Specify sender to limit scope
@receiver(post_save, sender=MyModel)
def handler(sender, instance, **kwargs):
    print(f"Signal from {sender.__name__}")
📊

Quick Reference

Use this quick guide to remember how to use the @receiver decorator:

ConceptDescription
@receiver(signal, sender=SenderClass)Connects a function to a signal, optionally filtering by sender.
signalA Django signal like post_save, pre_delete, etc.
senderOptional model or class sending the signal to filter events.
Handler function paramssender, instance, created (if applicable), and **kwargs.
Import locationPlace signal handlers in apps.py or a signals.py file imported on app startup.

Key Takeaways

Use the @receiver decorator to cleanly connect functions to Django signals.
Always specify the sender to limit signal handling to a specific model when needed.
Ensure your handler function has the correct parameters to receive signal data.
Place signal handlers in files that are imported when Django starts to activate them.
Common signals include post_save, pre_save, post_delete, and more.