0
0
DjangoHow-ToBeginner · 4 min read

How to Use Signals in Django: Simple Guide with Examples

In Django, signals let you run code automatically when certain actions happen, like saving a model. You connect a receiver function to a signal using the @receiver decorator or signal.connect(), so your code runs when the event occurs.
📐

Syntax

Django signals use a signal object and a receiver function that listens for that signal. You connect them with the @receiver decorator or signal.connect(). The receiver function must accept sender, instance, and **kwargs parameters.

  • signal: The event to listen for (e.g., post_save).
  • receiver: The function that runs when the signal fires.
  • sender: The model or class sending the signal.
python
from django.db.models.signals import post_save
from django.dispatch import receiver
from myapp.models import MyModel

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

Example

This example shows how to print a message whenever a new Book model instance is created using the post_save signal.

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

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 signal or receiver causes the handler not to run.
  • Not connecting the signal properly (missing sender or wrong signal) means your code won't trigger.
  • Placing signal handlers in files that are not imported on startup prevents them from registering.
  • Using signals for complex logic can make debugging harder; prefer explicit calls when possible.
python
from django.db.models.signals import post_save
from django.dispatch import receiver
from myapp.models import MyModel

# Wrong: Not specifying sender, so handler runs for all models
@receiver(post_save)
def handler(sender, instance, **kwargs):
    print("This runs for every model save, which may be unintended.")

# Right: Specify sender to limit to one model
@receiver(post_save, sender=MyModel)
def handler(sender, instance, **kwargs):
    print("Runs only when MyModel is saved.")
📊

Quick Reference

Remember these key points when using Django signals:

  • Use @receiver(signal, sender=Model) to connect handlers.
  • Handler functions must accept sender, instance, and **kwargs.
  • Common signals: pre_save, post_save, pre_delete, post_delete.
  • Import signal handlers in apps.py or ready() method to ensure registration.

Key Takeaways

Connect a receiver function to a Django signal using @receiver or signal.connect().
Receiver functions must accept sender, instance, and **kwargs parameters.
Signals run automatically on events like model save or delete to trigger custom code.
Always import and register signal handlers properly to ensure they work.
Avoid complex logic in signals to keep code easier to debug and maintain.