Signals let parts of your Django app talk to each other automatically when something happens. They help keep your code organized and avoid repeating yourself.
0
0
When signals are appropriate vs not in Django
Introduction
You want to run some code right after saving a model, like sending a welcome email.
You need to update related data automatically when something changes.
You want to keep your app modular by separating concerns cleanly.
You want to trigger actions on events without changing the original code.
You want to log or audit changes in your models without cluttering model methods.
Syntax
Django
from django.db.models.signals import post_save from django.dispatch import receiver @receiver(post_save, sender=YourModel) def your_handler(sender, instance, created, **kwargs): if created: # do something when a new instance is created pass
Use @receiver decorator to connect a function to a signal.
The handler function receives the sender model, the instance, and extra info.
Examples
This runs only when a new User is created, to send a welcome email.
Django
from django.db.models.signals import post_save from django.dispatch import receiver @receiver(post_save, sender=User) def send_welcome_email(sender, instance, created, **kwargs): if created: print(f"Send welcome email to {instance.email}")
This runs before an Article is deleted, useful for logging.
Django
from django.db.models.signals import pre_delete from django.dispatch import receiver @receiver(pre_delete, sender=Article) def log_article_deletion(sender, instance, **kwargs): print(f"Article {instance.title} is about to be deleted")
Sample Program
This example shows a signal that warns when product stock is low after saving.
Django
from django.db import models from django.db.models.signals import post_save from django.dispatch import receiver class Product(models.Model): name = models.CharField(max_length=100) stock = models.IntegerField(default=0) @receiver(post_save, sender=Product) def notify_low_stock(sender, instance, **kwargs): if instance.stock < 5: print(f"Warning: Low stock for {instance.name}") # Simulate saving products p1 = Product(name='Pen', stock=10) p1.save() # No warning p2 = Product(name='Notebook', stock=3) p2.save() # Warning printed
OutputSuccess
Important Notes
Signals can make debugging harder if overused because the flow is less obvious.
Don't use signals for complex business logic; keep them for simple side effects.
For very simple cases, calling functions directly might be clearer than signals.
Summary
Use signals to react automatically to model events without changing model code.
Signals are great for small side tasks like notifications or logging.
Avoid signals when the logic is complex or when direct calls are simpler and clearer.