patternpythondjangoModerate
Django signals — post_save for side effects and decoupling
Viewed 0 times
Django 3.2+
signalspost_savereceiverAppConfigside effectsdecoupling
Error Messages
Problem
Triggering side effects (sending emails, updating caches, creating related objects) inside model save() or views creates tight coupling and makes code harder to test.
Solution
Use Django signals (post_save, post_delete, m2m_changed) to react to model changes. Connect using @receiver decorator in apps.py ready() to ensure signal registration.
# signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import User
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
# apps.py
class UsersConfig(AppConfig):
name = 'users'
def ready(self):
import users.signals # noqa: F401 — registers signal handlersWhy
Signals implement the observer pattern. post_save fires after the DB save transaction. Connecting in AppConfig.ready() ensures handlers are registered after the app registry is fully loaded, avoiding AppRegistryNotReady errors.
Gotchas
- Signals fire inside the current transaction — if the transaction rolls back, the signal effect (e.g., email sent) already happened
- dispatch_uid='unique_string' prevents duplicate signal registration in environments that import modules multiple times
- Signals add hidden coupling that's hard to trace — overuse leads to debugging nightmares
- bulk operations (QuerySet.update(), bulk_create()) do NOT trigger signals
- Use transaction.on_commit() inside the signal handler for post-transaction side effects like sending emails
Context
Django apps where model changes need to trigger side effects like profile creation or cache invalidation
Revisions (0)
No revisions yet.