![]() |
VOOZH | about |
Signals provide a way to respond to actions occurring within an application. They allow tasks like logging, cache invalidation, or automatic data updates to execute without tightly coupling the code. Signals follow a publish-subscribe pattern, where a sender broadcasts an event and receivers handle it.
Django provides around 20 built-in signals, organized by category. They trigger at specific points in the framework lifecycle, allowing applications to respond to events such as model saves, deletions, or request/response processing.
| Signal | When Itβs Triggered | Key Arguments |
|---|---|---|
| pre_save | Before a model instance is saved | sender, instance, raw, using, update_fields |
| post_save | After a model instance is saved | sender, instance, created, raw, using, update_fields |
| pre_delete | Before a model instance is deleted | sender, instance, using |
| post_delete | After a model instance is deleted | sender, instance, using |
| m2m_changed | When a ManyToMany field is modified | sender, instance, action, pk_set, using |
| Signal | When Itβs Triggered | Key Arguments |
|---|---|---|
| request_started | When Django starts processing a request | sender |
| request_finished | When Django finishes processing a request | sender |
| got_request_exception | When an exception occurs in a view | request |
| Signal | When Itβs Triggered | Key Arguments |
|---|---|---|
| connection_created | When a new database connection is opened | connection |
| post_migrate | After migrations run for an app | sender, app_config, verbosity, interactive, using, apps |
Connect to these via decorators or methods. Always specify sender for efficiency.
Signals in Django need receiver functions to respond when an event is triggered. Receivers can be connected and disconnected using decorators or the connect()/disconnect() methods.
To stop a receiver from listening:
post_save.disconnect(create_profile, sender=CustomUser)
This can be useful in tests or temporary signal handling. Always specify the sender when connecting to signals. It reduces unnecessary function calls and improves performance.
Built-in signals fire automatically, but custom signals can be sent manually when needed.
This allows custom events to trigger multiple receivers in a clean and decoupled way.
Django signals allow decoupled components to get notified when certain actions occur. The flow works as follows:
1. Define or Use a Signal
2. Connect a Receiver
3. Send the Signal
4. Receiver Executes
Consider a project named 'userprofile_project' having an app named 'users'.
Automatically create a profile for every new user upon registration.
models.py: Each user has a profile linked via a one-to-one relationship.
views.py:
forms.py: Defines forms for user registration and profile updates.
signals.py(Using receiver method): Automatically creates and saves a profile when a User is created.
When the User model is saved, a signal called create_profile is fired. This signal creates a Profile instance with a foreign key pointing to the saved User instance. The save_profile signal ensures that the profile instance is also saved after the user is saved.
Signals can also be loaded automatically using AppConfig:
The signal resides in the signals.py file of the app.
If user is created:
π ImageThen his profile is automatically created:
π ImageCheck it in admin view:
π ImageThe pre_save signal is triggered immediately before a model's save() method is executed. The model is saved only after the pre_save signal completes successfully.
This signal ensures actions are executed conditionally, for example, only if a specific field has changed.
Signals can also be connected without decorators by using the connect() method. This is an alternative to the @receiver decorator.
This method provides the same functionality as receiver decorators, allowing explicit control over which functions handle which signals.
Signals promote loose coupling by notifying external handlers instead of embedding side effects directly in model methods.
| Advantage | Drawback / Consideration |
|---|---|
| Reusability: A single signal can trigger multiple receivers across different apps. | Performance: Each signal emission calls all connected receivers, which may impact high-traffic applications. |
| Separation of Concerns: Models remain lean while tasks like sending emails or updating caches are handled externally. | Debugging: Side effects triggered by signals are less explicit and harder to trace. |
| Extensibility: Third-party apps can connect to signals without modifying existing code. | Execution Order: Receivers execute in connection order, not a guaranteed sequence. |