Signals and application side effects¶
The canonical model signal guide documents the four built-in events, exact payloads, explicit connection API, exception behavior, and a runnable custom-signal example.
Choose the right mechanism¶
| Requirement | Approach |
|---|---|
| Normalize an individual model save | A small pre_save receiver; do not assume it covers bulk or raw writes. |
| Validate all supported write paths | Explicit input validation and appropriate database constraints. |
| Commit related database mutations together | An explicit transaction using the same pinned connection. |
| Run ordinary asynchronous work | Background tasks, with their documented retry and delivery limits. |
| Recover authorized work after worker loss | Durable Operations, including explicit external-outcome handling. |
A callback is not commit evidence¶
post_save describes where a callback runs relative to the model's SQL work.
It does not mean the outer transaction committed. A notification or search-index
write performed there can survive a database rollback; a process crash can
also prevent a callback from running after a committed statement.
For audit requirements, identify the write paths that must be covered and the retention and transaction guarantees required. Model callbacks alone do not cover arbitrary SQL, all bulk operations, or durable delivery. Avoid recording an entire model dictionary without a deliberate sensitive-field policy.
Test subscriptions, not patched names¶
A connected receiver is a stored callable. Patching the module attribute after
connection does not replace that stored callback. Connect the test receiver
explicitly and disconnect it in finally. Test both successful dispatch and
receiver failures; separately test database rollback and external effects when
those are part of the application contract.