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)