When building a Django application, you often need to perform actions whenever something specific happens β for example, sending a welcome email after a user registers.
Instead of writing extra logic inside your views or models, Django gives us a powerful feature: Signals.
In this post, weβll break down what signals are, why you need them, and a real-world example with code.
π What are Django Signals?
Django Signals allow decoupled applications to get notified when certain actions occur.
Think of them like a notification system inside Django.
β’ Event happens β Signal is fired
β’ Listener catches it β Executes extra logic
Examples:
β’ A user logs in β Update last login timestamp
β’ A new order is created β Send invoice email
β’ A profile is saved β Resize uploaded avatar
π οΈ Common Built-in Signals
Django comes with some built-in signals:
β’ pre_save / post_save β before/after saving a model
β’ pre_delete / post_delete β before/after deleting a model
β’ m2m_changed β when a ManyToMany relation is updated
β’ request_started / request_finished β when a request starts/ends
β’ user_logged_in / user_logged_out β authentication-related signals
You can also create custom signals.
π§βπ» Example: Auto-Creating a Profile When a User Registers
Instead of writing profile creation logic inside the signup view, letβs use signals.
Step 1: Create a Profile model
# app/models.py
from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField(blank=True)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"{self.user.username}'s profile"
Step 2: Write a Signal Receiver
# app/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_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
Hereβs what happens:
β’ When a new User is created β post_save signal is fired.
β’ Our create_user_profile function catches it.
β’ A Profile is automatically created for the new user.
Step 3: Connect the Signal in apps.py
# app/apps.py
from django.apps import AppConfig
class AppConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'app'
def ready(self):
import app.signals
Now, whenever a new user registers, Django automatically creates a profile without extra code in the view.
β‘ Why Use Signals?
β
Keeps code clean & decoupled
β
Avoids duplicate logic across views
β
Makes your app event-driven
β οΈ When NOT to Use Signals?
β’ When the logic is very specific to one place (better to keep it in the view).
β’ When debugging complex chains (signals can make code harder to trace).
β’ If overused β can create βhidden logicβ thatβs difficult for teams to maintain.
π― Final Thoughts
Django Signals are a game-changer for clean and modular code. Use them wisely to automate side-effects like profile creation, notifications, and logging.
π If you found this helpful, drop a β€οΈ or share your thoughts in the comments.
Top comments (0)