Connecting Receivers Properly
Register signals in apps.py to avoid pitfalls.
Connecting Receivers Properly is a free Django Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Django Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Receivers Must Be Imported
A receiver only listens if Django actually imports the module it lives in. If the file is never loaded, the signal silently does nothing.
The Classic Trap
Putting receivers in models.py sometimes works by luck, and sometimes not. That fragility is the connection problem you want to avoid.
Use a signals.py File
The clean pattern is a dedicated signals.py inside your app that holds every receiver for that app in one obvious place.
from django.db.models.signals import post_save
from django.dispatch import receiver
@receiver(post_save, sender=Profile)
def sync(sender, instance, **kwargs):
passThe AppConfig.ready Hook
Django calls ready() on each app config once at startup. That is the official place to load your signal handlers.
Import Inside ready
In apps.py, import your signals module from inside ready so receivers register exactly once when the app boots.
from django.apps import AppConfig
class BlogConfig(AppConfig):
name = "blog"
def ready(self):
from . import signalsPoint default_app_config
Make sure your app uses that config. Modern Django auto-discovers apps.py, so a matching AppConfig class is usually enough.
connect Without a Decorator
Instead of @receiver, you can wire a handler with connect. It does the same job and is handy for dynamic registration.
post_save.connect(sync, sender=Profile)Avoiding Double Firing
If a module is imported twice, a receiver can run twice. Centralizing registration in ready() keeps each handler connected only once.
The dispatch_uid Safety Net
Pass a unique dispatch_uid so Django refuses to connect the same receiver more than once, even across reimports.
post_save.connect(sync, sender=Profile, dispatch_uid="profile_sync")Disconnecting Receivers
You can also call disconnect to stop a handler, which is useful inside tests that should not trigger side effects.
Keep One App's Signals Together
Grouping each app's handlers in its own signals.py keeps reactions discoverable and stops them from scattering across the codebase.
Quick Check
Recall where signal handlers should be registered.
Recap: Wiring Signals Right
You learned to keep receivers in a signals.py, import them from AppConfig.ready(), and use dispatch_uid to prevent duplicate connections. ✅
Frequently asked questions
Is the “Connecting Receivers Properly” lesson free?
Yes — the full text of “Connecting Receivers Properly” is free to read here on the web, and the Django Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Django Academy course, upgrade to CoddyKit PRO.
What will I learn in “Connecting Receivers Properly”?
Register signals in apps.py to avoid pitfalls. You practise Django Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Django Academy?
No prior experience is required. Django Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Connecting Receivers Properly” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Django Academy lesson?
Yes. Every Django Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- post_save and pre_delete Signals
- Connecting Receivers Properly
- Writing Custom Middleware
- Middleware Order and process_view