📡
Django Signals — イベントベースの疎結合
post_save、pre_deleteが内部的にどう動くか
内部実装
django.dispatch.Signalは内部にreceiversリストを持つ。connect()で関数を登録、send()で全登録関数を順次呼び出し。
post_save.send()はModel.save()内部で呼ばれる。
なぜ注意が必要か
- 暗黙的実行 — 明示的呼び出しがコードにないため「誰がこれを呼んでいる?」
- 順序保証なし — receiver実行順序は登録順に依存するが保証ではない
- トランザクション問題 — post_saveはトランザクションコミット前に実行される可能性。
transaction.on_commit()使用推奨 - テスト複雑性 — Signalがテストでも発動し予期せぬ副作用
代替案:明示的サービス関数呼び出しの方が追跡しやすい。Signalは「アプリ境界を跨ぐ疎結合」が必要な時だけ。
キーポイント
1
Signal.connect()でreceiver関数を登録
2
Model.save()内部でpost_save.send()呼び出し→登録済みreceiver全て実行
3
receiverはsender、instance、created等の引数を受け取る
4
トランザクション安全のためtransaction.on_commit()内で処理推奨
ユースケース
ユーザー作成時プロフィール自動生成
注文完了時通知送信(アプリ間疎結合)