What are Django signals and when should you use them?
Learn what Django signals are, common built-in signals, how to connect receivers in AppConfig.ready(), and when to use them versus overriding save().
Expected Interview Answer
Django signals are a publish/subscribe mechanism that lets decoupled parts of an application react to events — like a model being saved or deleted — by connecting receiver functions to senders without the sender knowing who is listening.
Built-in signals such as pre_save, post_save, pre_delete, post_delete, m2m_changed, and request_started are dispatched by Django's dispatcher. You register a receiver with the @receiver decorator or Signal.connect(), usually wiring it up in an app's ready() method inside apps.py. Signals are best for cross-cutting side effects that must stay separate from core logic; when the action naturally belongs to the model or view, an explicit method call or overridden save() is clearer and easier to test.
- Decouples side effects from core business logic
- Lets reusable apps react to events they do not own
- Centralizes cross-cutting concerns like auditing or cache invalidation
- Supports both built-in and custom signals
- Avoids editing third-party model code to add behavior
AI Mentor Explanation
A signal is like the third umpire's review system: the on-field umpire (the model save) does not need to know who is watching, but a review request is broadcast and any interested official — scorer, broadcaster, DRS operator — reacts on their own. Django's dispatcher broadcasts an event and each connected receiver responds without the batter or bowler ever calling them directly.
Step-by-Step Explanation
Step 1
Identify the event
Choose a signal such as post_save, pre_delete, or a custom Signal that represents the moment you want to react to.
Step 2
Write the receiver
Define a function accepting sender and **kwargs; it contains the side-effect logic like creating a profile or clearing a cache.
Step 3
Connect the receiver
Use the @receiver(post_save, sender=User) decorator or Signal.connect() to bind the receiver to a specific sender.
Step 4
Wire it in AppConfig.ready()
Import the signals module inside the app's ready() method so registration happens once at startup.
Step 5
Guard for created vs updated
In post_save, check the created flag to avoid re-running create-only logic on every update.
What Interviewer Expects
- Naming common built-in signals and their timing
- Knowing receivers connect via decorator or connect()
- Registering signals in AppConfig.ready()
- Understanding when a direct method call is better than a signal
- Awareness that signals run synchronously in the same request
Common Mistakes
- Registering receivers at import time in the wrong place, causing duplicate firing
- Using signals for logic that belongs in the model's save() method
- Forgetting the created flag and re-running create logic on updates
- Assuming signals are asynchronous when they run inline and block the request
- Overusing signals until control flow becomes hard to trace
Best Answer (HR Friendly)
“Django signals let one part of the app quietly announce that something happened, like a user was created, so other parts can react automatically without being directly tied together. You use them for behind-the-scenes side effects, but for logic that clearly belongs to the main flow, a direct function call is usually cleaner.”
Code Example
# signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth.models import User
from .models import Profile
@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
# apps.py
from django.apps import AppConfig
class AccountsConfig(AppConfig):
name = 'accounts'
def ready(self):
from . import signals # noqa: F401 register receiversFollow-up Questions
- How do you register signal receivers so they fire exactly once?
- What is the difference between pre_save and post_save?
- Are Django signals synchronous or asynchronous?
- How do you create and send a custom signal?
- When would you override save() instead of using a signal?
MCQ Practice
1. Which method is the recommended place to connect signal receivers?
Importing the signals module inside AppConfig.ready() ensures receivers are registered once when the app is loaded.
2. In a post_save receiver, how do you tell a new record from an update?
post_save passes a created boolean that is True only when the instance was newly inserted.
3. Which statement about Django signals is correct?
Signals are dispatched inline and synchronously, so a slow receiver blocks the request unless you offload work yourself.
Flash Cards
What is a Django signal? — A publish/subscribe event that lets receivers react to actions like save or delete without the sender knowing them.
Common built-in signals? — pre_save, post_save, pre_delete, post_delete, m2m_changed, request_started/finished.
Where should receivers be registered? — By importing the signals module inside the AppConfig.ready() method.
Are signals async? — No — they run synchronously inline, so heavy work should be offloaded to a task queue.