{"title":"シグナル","version":"6.0","locale":"ja","docname":"topics/signals","url":"/ja/6.0/topics/signals/","canonical":"https://djangodocs.dev/ja/6.0/topics/signals/","summary":"Django には \"シグナルディスパッチャ\" があり、フレームワークの他の場所でアクションが発生したときに、ほかのアプリケーションが通知を受けるのを助けてくれます。簡単に言うと、シグナルは特定の 送り手 が、あるアクションが発生したことを一連の 受け手…","html":"<span id=\"signals\"></span><h1>シグナル<a class=\"heading-anchor\" href=\"#module-django.dispatch\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>Django には &quot;シグナルディスパッチャ&quot; があり、フレームワークの他の場所でアクションが発生したときに、ほかのアプリケーションが通知を受けるのを助けてくれます。簡単に言うと、シグナルは特定の <em>送り手</em> が、あるアクションが発生したことを一連の <em>受け手</em> に通知できるようにします。特に、多くのコードが同じイベントに関連している場合に便利です。</p>\n<p>例えば、サードパーティのアプリを登録して、設定変更の通知を受けることができます:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.apps</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">AppConfig</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.core.signals</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">setting_changed</span>\n\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_callback</span><span class=\"p\">(</span><span class=\"n\">sender</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n    <span class=\"nb\">print</span><span class=\"p\">(</span><span class=\"s2\">&quot;Setting changed!&quot;</span><span class=\"p\">)</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MyAppConfig</span><span class=\"p\">(</span><span class=\"n\">AppConfig</span><span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">ready</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"n\">setting_changed</span><span class=\"o\">.</span><span class=\"n\">connect</span><span class=\"p\">(</span><span class=\"n\">my_callback</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Django の <a class=\"reference internal\" href=\"/ja/6.0/ref/signals/\"><span class=\"doc\">組み込みのシグナル</span></a> は、ユーザコードに特定のアクションを通知します。</p>\n<p>また、独自のカスタムシグナルを定義して送信することもできます。以下の <a class=\"reference internal\" href=\"#defining-and-sending-signals\"><span class=\"std std-ref\">シグナルの定義と送信</span></a> を参照してください。</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">警告</p>\n<p>シグナルは疎結合のように見えますが、すぐに理解や調整、デバッグが難しいコードにつながります。</p>\n<p>可能であれば、シグナルでディスパッチするのではなく、処理コードを直接呼び出すことを選ぶべきです。</p>\n</aside>\n<section id=\"listening-to-signals\">\n<h2>シグナルを待ち受ける<a class=\"heading-anchor\" href=\"#listening-to-signals\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>シグナルを受信するには、 <a class=\"reference internal\" href=\"#django.dispatch.Signal.connect\" title=\"django.dispatch.Signal.connect\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">Signal.connect()</span></code></a> メソッドを使って <em>receiver</em> 関数を登録します。シグナルが送信されると、レシーバ関数が呼び出されます。シグナルのすべてのレシーバ関数は、登録された順番に1つずつ呼び出されます。</p>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.dispatch.Signal.connect\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">Signal.</span></span><span class=\"sig-name descname\"><span class=\"pre\">connect</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">receiver</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">sender</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">weak</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">True</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">dispatch_uid</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.dispatch.Signal.connect\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><dl class=\"field-list simple\">\n<dt class=\"field-odd\">パラメータ<span class=\"colon\">:</span></dt>\n<dd class=\"field-odd\"><ul class=\"simple\">\n<li><p><strong>receiver</strong> -- このシグナルに接続されるコールバック関数です。詳しくは <a class=\"reference internal\" href=\"#receiver-functions\"><span class=\"std std-ref\">レシーバ関数</span></a> を参照してください。</p></li>\n<li><p><strong>sender</strong> -- シグナルを受信する送信者を指定します。詳しくは <a class=\"reference internal\" href=\"#connecting-to-specific-signals\"><span class=\"std std-ref\">特定の送信者によって送られたシグナルに接続する</span></a> を参照してください。</p></li>\n<li><p><strong>weak</strong> -- Django はデフォルトでシグナルハンドラを弱い参照として保存します。従って、レシーバがローカル関数の場合、ガベージコレクションされる可能性 があります。これを防ぐには、シグナルの <code class=\"docutils literal notranslate\"><span class=\"pre\">connect()</span></code> メソッドを呼び出すときに <code class=\"docutils literal notranslate\"><span class=\"pre\">weak=False</span></code> を渡してください。</p></li>\n<li><p><strong>dispatch_uid</strong> -- シグナルが重複して送信される可能性がある場合の、シグナル受信機の一意な識別子。詳しくは <a class=\"reference internal\" href=\"#preventing-duplicate-signals\"><span class=\"std std-ref\">重複したシグナルを防止する</span></a> を参照してください。</p></li>\n</ul>\n</dd>\n</dl>\n</dd></dl>\n\n<p>HTTP リクエストが終了するたびに呼び出されるシグナルを登録することで、この仕組みを見てみましょう。ここでは <a class=\"reference internal\" href=\"/ja/6.0/ref/signals/#django.core.signals.request_finished\" title=\"django.core.signals.request_finished\"><code class=\"xref py py-data docutils literal notranslate\"><span class=\"pre\">request_finished</span></code></a> シグナルに接続します。</p>\n<section id=\"receiver-functions\">\n<span id=\"id1\"></span><h3>レシーバ関数<a class=\"heading-anchor\" href=\"#receiver-functions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>まず、レシーバ関数を定義する必要があります。レシーバはPythonの関数やメソッドであれば何でもかまいません:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_callback</span><span class=\"p\">(</span><span class=\"n\">sender</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n    <span class=\"nb\">print</span><span class=\"p\">(</span><span class=\"s2\">&quot;Request finished!&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>この関数は <code class=\"docutils literal notranslate\"><span class=\"pre\">sender</span></code> 引数とワイルドカードキーワード引数 (<code class=\"docutils literal notranslate\"><span class=\"pre\">**kwargs</span></code>) を取ることに注意してください。すべてのシグナルハンドラはこれらの引数を取らなければなりません。</p>\n<p>送信者については <a class=\"reference internal\" href=\"#connecting-to-specific-signals\"><span class=\"std std-ref\">もう少し後で</span></a> 見るので、今は <code class=\"docutils literal notranslate\"><span class=\"pre\">**kwargs</span></code> 引数を見てください。すべてのシグナルはキーワード引数を送信し、いつでもそのキーワード引数を変更できます。 <a class=\"reference internal\" href=\"/ja/6.0/ref/signals/#django.core.signals.request_finished\" title=\"django.core.signals.request_finished\"><code class=\"xref py py-data docutils literal notranslate\"><span class=\"pre\">request_finished</span></code></a> の場合、引数を送らないようにドキュメント化されているので、シグナル処理を <code class=\"docutils literal notranslate\"><span class=\"pre\">my_callback(sender)</span></code> と書きたくなるかもしれません。</p>\n<p>これは間違いです。実際、そうすると Django はエラーを返します。というのも、シグナルに引数が追加される可能性があり、レシーバはその新しい引数を扱えなければならないからです。</p>\n<p>レシーバーは同じシグネチャーを持ち、<code class=\"docutils literal notranslate\"><span class=\"pre\">async</span> <span class=\"pre\">def</span></code> を使って宣言された非同期関数になることもできます:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">async</span> <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_callback</span><span class=\"p\">(</span><span class=\"n\">sender</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n    <span class=\"k\">await</span> <span class=\"n\">asyncio</span><span class=\"o\">.</span><span class=\"n\">sleep</span><span class=\"p\">(</span><span class=\"mi\">5</span><span class=\"p\">)</span>\n    <span class=\"nb\">print</span><span class=\"p\">(</span><span class=\"s2\">&quot;Request finished!&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>シグナルは同期でも非同期でも送ることができ、受信側は自動的に正しいコールスタイルに合わせられます。詳細は <a class=\"reference internal\" href=\"#sending-signals\"><span class=\"std std-ref\">シグナルを送る</span></a> を参照してください。</p>\n</section>\n<section id=\"connecting-receiver-functions\">\n<span id=\"id2\"></span><h3>レシーバ関数に接続する<a class=\"heading-anchor\" href=\"#connecting-receiver-functions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>受信機を信号に接続する方法は2つあります。手動で接続する方法です:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.core.signals</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">request_finished</span>\n\n<span class=\"n\">request_finished</span><span class=\"o\">.</span><span class=\"n\">connect</span><span class=\"p\">(</span><span class=\"n\">my_callback</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>あるいは、 <a class=\"reference internal\" href=\"#django.dispatch.receiver\" title=\"django.dispatch.receiver\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">receiver()</span></code></a> デコレータを使うこともできます:</p>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.dispatch.receiver\">\n<span class=\"sig-name descname\"><span class=\"pre\">receiver</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">signal</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">kwargs</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.dispatch.receiver\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><dl class=\"field-list simple\">\n<dt class=\"field-odd\">パラメータ<span class=\"colon\">:</span></dt>\n<dd class=\"field-odd\"><ul class=\"simple\">\n<li><p><strong>signal</strong> -- 関数を接続するシグナルまたはシグナルのリスト。</p></li>\n<li><p><strong>kwargs</strong> -- <a class=\"reference internal\" href=\"#receiver-functions\"><span class=\"std std-ref\">関数</span></a> に渡すワイルドカードキーワード引数です。</p></li>\n</ul>\n</dd>\n</dl>\n</dd></dl>\n\n<p>下記がデコレーターとの繋げ方です:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.core.signals</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">request_finished</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.dispatch</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">receiver</span>\n\n\n<span class=\"nd\">@receiver</span><span class=\"p\">(</span><span class=\"n\">request_finished</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_callback</span><span class=\"p\">(</span><span class=\"n\">sender</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n    <span class=\"nb\">print</span><span class=\"p\">(</span><span class=\"s2\">&quot;Request finished!&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>これで、リクエストが終了するたびに <code class=\"docutils literal notranslate\"><span class=\"pre\">my_callback</span></code> 関数が呼ばれるようになります。</p>\n<aside class=\"admonition-where-should-this-code-live admonition\">\n<p class=\"admonition-title\">コードはどこに置くの？</p>\n<p>厳密には、シグナル処理と登録のコードは好きな場所に置くことができますが、コードのインポートによる副作用を最小限にするために、アプリケーションのルートモジュールと <code class=\"docutils literal notranslate\"><span class=\"pre\">models</span></code> モジュールの置くのは避けることを推奨します。</p>\n<p>実際には、シグナルハンドラは通常、関連するアプリケーションの <code class=\"docutils literal notranslate\"><span class=\"pre\">signals</span></code> サブモジュールで定義されます。シグナルレシーバーはアプリケーションの  <a class=\"reference internal\" href=\"/ja/6.0/ref/applications/#configuring-applications-ref\"><span class=\"std std-ref\">configuration クラス</span></a> の <a class=\"reference internal\" href=\"/ja/6.0/ref/applications/#django.apps.AppConfig.ready\" title=\"django.apps.AppConfig.ready\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">ready()</span></code></a> メソッドで接続されます。 <a class=\"reference internal\" href=\"#django.dispatch.receiver\" title=\"django.dispatch.receiver\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">receiver()</span></code></a> デコレータを使っている場合は、 <a class=\"reference internal\" href=\"/ja/6.0/ref/applications/#django.apps.AppConfig.ready\" title=\"django.apps.AppConfig.ready\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">ready()</span></code></a> の中にある <code class=\"docutils literal notranslate\"><span class=\"pre\">signals</span></code> サブモジュールをインポートしてください、これによりシグナルハンドラが暗黙的に接続されます:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.apps</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">AppConfig</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.core.signals</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">request_finished</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MyAppConfig</span><span class=\"p\">(</span><span class=\"n\">AppConfig</span><span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">ready</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Implicitly connect signal handlers decorated with @receiver.</span>\n        <span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">.</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">signals</span>\n\n        <span class=\"c1\"># Explicitly connect a signal handler.</span>\n        <span class=\"n\">request_finished</span><span class=\"o\">.</span><span class=\"n\">connect</span><span class=\"p\">(</span><span class=\"n\">signals</span><span class=\"o\">.</span><span class=\"n\">my_callback</span><span class=\"p\">)</span>\n</code></pre></div>\n</aside>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">注釈</p>\n<p>The <a class=\"reference internal\" href=\"/ja/6.0/ref/applications/#django.apps.AppConfig.ready\" title=\"django.apps.AppConfig.ready\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">ready()</span></code></a> method may be executed more than\nonce during testing, so you may want to <a class=\"reference internal\" href=\"#preventing-duplicate-signals\"><span class=\"std std-ref\">guard your signals from\nduplication</span></a> if your receiver is a bound\nmethod on an instance that may be recreated.</p>\n</aside>\n</section>\n<section id=\"connecting-to-signals-sent-by-specific-senders\">\n<span id=\"connecting-to-specific-signals\"></span><h3>特定の送信者によって送られたシグナルに接続する<a class=\"heading-anchor\" href=\"#connecting-to-signals-sent-by-specific-senders\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>シグナルの中には何度も送信されるものがありますが、そのようなシグナルの特定のサブセットだけを受信したいと思うかも知れません。例えば、モデルが保存される前に送られるシグナル <a class=\"reference internal\" href=\"/ja/6.0/ref/signals/#django.db.models.signals.pre_save\" title=\"django.db.models.signals.pre_save\"><code class=\"xref py py-data docutils literal notranslate\"><span class=\"pre\">django.db.models.signals.pre_save</span></code></a> を考えてみましょう。ほとんどの場合、 <em>どの</em> モデルが保存されるかを知る必要はありません。ある <em>特定の</em> モデルが保存されたときだけ知る必要があります。</p>\n<p>このような場合、特定の送信者のみが送信するシグナルを受信するように登録できます。 <a class=\"reference internal\" href=\"/ja/6.0/ref/signals/#django.db.models.signals.pre_save\" title=\"django.db.models.signals.pre_save\"><code class=\"xref py py-data docutils literal notranslate\"><span class=\"pre\">django.db.models.signals.pre_save</span></code></a> の場合、送信者は保存されるモデルクラスになるので、あるモデルから送信されるシグナルだけが欲しいことを示すことができます:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models.signals</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">pre_save</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.dispatch</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">receiver</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">myapp.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">MyModel</span>\n\n\n<span class=\"nd\">@receiver</span><span class=\"p\">(</span><span class=\"n\">pre_save</span><span class=\"p\">,</span> <span class=\"n\">sender</span><span class=\"o\">=</span><span class=\"n\">MyModel</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_handler</span><span class=\"p\">(</span><span class=\"n\">sender</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span> <span class=\"o\">...</span>\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">my_handler</span></code> 関数は <code class=\"docutils literal notranslate\"><span class=\"pre\">MyModel</span></code> のインスタンスが保存されたときにだけ呼び出されます。</p>\n<p>異なるシグナルは異なるオブジェクトを送信元として使用します。それぞれのシグナルの詳細については <a class=\"reference internal\" href=\"/ja/6.0/ref/signals/\"><span class=\"doc\">組み込みシグナルのドキュメント</span></a> を参照する必要があります。</p>\n</section>\n<section id=\"preventing-duplicate-signals\">\n<span id=\"id3\"></span><h3>重複したシグナルを防止する<a class=\"heading-anchor\" href=\"#preventing-duplicate-signals\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>When <code class=\"docutils literal notranslate\"><span class=\"pre\">dispatch_uid</span></code> is not provided, Django identifies each receiver using\nits Python object identity and registers it only once. For module-level\nfunctions, static methods, and class methods, the identity is stable, so\nconnecting the same receiver more than once has no effect:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_handler</span><span class=\"p\">(</span><span class=\"n\">sender</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span> <span class=\"o\">...</span>\n\n\n<span class=\"n\">my_signal</span><span class=\"o\">.</span><span class=\"n\">connect</span><span class=\"p\">(</span><span class=\"n\">my_handler</span><span class=\"p\">)</span>  <span class=\"c1\"># Running this code again is a no-op.</span>\n</code></pre></div>\n<p>Bound methods, which take a <code class=\"docutils literal notranslate\"><span class=\"pre\">self</span></code> argument, are different. Their identity\nis tied to the specific instance, so connecting the same method from a new\ninstance registers it as an additional receiver:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">connect_signals</span><span class=\"p\">():</span>\n    <span class=\"n\">backend</span> <span class=\"o\">=</span> <span class=\"n\">Backend</span><span class=\"p\">()</span>\n    <span class=\"n\">my_signal</span><span class=\"o\">.</span><span class=\"n\">connect</span><span class=\"p\">(</span><span class=\"n\">backend</span><span class=\"o\">.</span><span class=\"n\">my_handler</span><span class=\"p\">)</span>  <span class=\"c1\"># A distinct receiver.</span>\n\n\n<span class=\"n\">connect_signals</span><span class=\"p\">()</span>  <span class=\"c1\"># Running this code again registers another receiver.</span>\n</code></pre></div>\n<p>When using a bound method as a receiver, multiple registrations can be\nprevented by supplying a unique <code class=\"docutils literal notranslate\"><span class=\"pre\">dispatch_uid</span></code>. This identifier will usually\nbe a string, although any hashable object will suffice. The receiver will only\nbe bound to the signal once for each unique <code class=\"docutils literal notranslate\"><span class=\"pre\">dispatch_uid</span></code> value:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.core.signals</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">request_finished</span>\n\n<span class=\"n\">request_finished</span><span class=\"o\">.</span><span class=\"n\">connect</span><span class=\"p\">(</span><span class=\"n\">my_callback</span><span class=\"p\">,</span> <span class=\"n\">dispatch_uid</span><span class=\"o\">=</span><span class=\"s2\">&quot;my_unique_identifier&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n</section>\n</section>\n<section id=\"defining-and-sending-signals\">\n<span id=\"id4\"></span><h2>シグナルの定義と送信<a class=\"heading-anchor\" href=\"#defining-and-sending-signals\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>アプリケーションは信号インフラを利用し、独自の信号を提供できます。</p>\n<aside class=\"admonition-when-to-use-custom-signals admonition\">\n<p class=\"admonition-title\">カスタムシグナルを使うべきタイミング</p>\n<p>シグナルは暗黙の関数呼び出しなので、デバッグが難しくなります。カスタムシグナルの送信側と受信側の両方がプロジェクト内にある場合は、明示的な関数呼び出しを使ったほうがよいでしょう。</p>\n</aside>\n<section id=\"defining-signals\">\n<h3>シグナルを定義する<a class=\"heading-anchor\" href=\"#defining-signals\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.dispatch.Signal\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">Signal</span></span><a class=\"heading-anchor\" href=\"#django.dispatch.Signal\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>すべてのシグナルは <a class=\"reference internal\" href=\"#django.dispatch.Signal\" title=\"django.dispatch.Signal\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">django.dispatch.Signal</span></code></a> インスタンスです。</p>\n<p>例:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">import</span><span class=\"w\"> </span><span class=\"nn\">django.dispatch</span>\n\n<span class=\"n\">pizza_done</span> <span class=\"o\">=</span> <span class=\"n\">django</span><span class=\"o\">.</span><span class=\"n\">dispatch</span><span class=\"o\">.</span><span class=\"n\">Signal</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>このコードは、<code class=\"docutils literal notranslate\"><span class=\"pre\">pizza_done</span></code> シグナルを宣言しています。</p>\n</section>\n<section id=\"sending-signals\">\n<span id=\"id5\"></span><h3>シグナルを送信する<a class=\"heading-anchor\" href=\"#sending-signals\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django でシグナルを同期的に送信する方法は2つあります。</p>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.dispatch.Signal.send\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">Signal.</span></span><span class=\"sig-name descname\"><span class=\"pre\">send</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">sender</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">kwargs</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.dispatch.Signal.send\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.dispatch.Signal.send_robust\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">Signal.</span></span><span class=\"sig-name descname\"><span class=\"pre\">send_robust</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">sender</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">kwargs</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.dispatch.Signal.send_robust\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>シグナルは非同期に送信することもできます。</p>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.dispatch.Signal.asend\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">Signal.</span></span><span class=\"sig-name descname\"><span class=\"pre\">asend</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">sender</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">kwargs</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.dispatch.Signal.asend\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.dispatch.Signal.asend_robust\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">Signal.</span></span><span class=\"sig-name descname\"><span class=\"pre\">asend_robust</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">sender</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">kwargs</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.dispatch.Signal.asend_robust\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>シグナルを送信するには、<a class=\"reference internal\" href=\"#django.dispatch.Signal.send\" title=\"django.dispatch.Signal.send\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">Signal.send()</span></code></a>、<a class=\"reference internal\" href=\"#django.dispatch.Signal.send_robust\" title=\"django.dispatch.Signal.send_robust\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">Signal.send_robust()</span></code></a>、<a class=\"reference internal\" href=\"#django.dispatch.Signal.asend\" title=\"django.dispatch.Signal.asend\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">await</span> <span class=\"pre\">Signal.asend()</span></code></a>、<a class=\"reference internal\" href=\"#django.dispatch.Signal.asend_robust\" title=\"django.dispatch.Signal.asend_robust\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">await</span> <span class=\"pre\">Signal.asend_robust()</span></code></a> のどれかを呼び出します。引数として <code class=\"docutils literal notranslate\"><span class=\"pre\">sender</span></code> (ほとんどの場合クラス) を指定する必要があり、他のキーワード引数を好きなだけ指定できます。</p>\n<p>たとえば、<code class=\"docutils literal notranslate\"><span class=\"pre\">pizza_done</span></code> シグナルを送信するには、次のようにします:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">PizzaStore</span><span class=\"p\">:</span>\n    <span class=\"o\">...</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">send_pizza</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">toppings</span><span class=\"p\">,</span> <span class=\"n\">size</span><span class=\"p\">):</span>\n        <span class=\"n\">pizza_done</span><span class=\"o\">.</span><span class=\"n\">send</span><span class=\"p\">(</span><span class=\"n\">sender</span><span class=\"o\">=</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"vm\">__class__</span><span class=\"p\">,</span> <span class=\"n\">toppings</span><span class=\"o\">=</span><span class=\"n\">toppings</span><span class=\"p\">,</span> <span class=\"n\">size</span><span class=\"o\">=</span><span class=\"n\">size</span><span class=\"p\">)</span>\n        <span class=\"o\">...</span>\n</code></pre></div>\n<p>4つのメソッドはすべて、呼び出されたレシーバー関数とそのレスポンス値のリストを表すタプルのペア <code class=\"docutils literal notranslate\"><span class=\"pre\">[(receiver,</span> <span class=\"pre\">response),</span> <span class=\"pre\">...]</span></code> のリストを返します。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">send()</span></code> は <code class=\"docutils literal notranslate\"><span class=\"pre\">send_robust()</span></code> と異なり、レシーバ関数が発生させた例外をどのようにハンド リングするかという点で異なります。 <code class=\"docutils literal notranslate\"><span class=\"pre\">send()</span></code> はレシーバが発生させた例外をキャッチしません。そのため、エラーが発生してもすべてのレシーバにシグナルが通知されるとは限りません。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">send_robust()</span></code> は Python の <code class=\"docutils literal notranslate\"><span class=\"pre\">Exception</span></code> クラスに由来するすべてのエラーをキャッチし、すべてのレシーバにシグナルが通知されるようにします。エラーが発生した場合、エラーを発生させたレシーバのタプルのペアにエラーインスタンスが返されます。</p>\n<p>トレースバックは <code class=\"docutils literal notranslate\"><span class=\"pre\">send_robust()</span></code> を呼び出したときに返されるエラーの <code class=\"docutils literal notranslate\"><span class=\"pre\">__traceback__</span></code> 属性に存在します。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">asend()</span></code> は <code class=\"docutils literal notranslate\"><span class=\"pre\">send()</span></code> と似ていますが、await しなければならないコルーチンです:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">async</span> <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">asend_pizza</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">toppings</span><span class=\"p\">,</span> <span class=\"n\">size</span><span class=\"p\">):</span>\n    <span class=\"k\">await</span> <span class=\"n\">pizza_done</span><span class=\"o\">.</span><span class=\"n\">asend</span><span class=\"p\">(</span><span class=\"n\">sender</span><span class=\"o\">=</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"vm\">__class__</span><span class=\"p\">,</span> <span class=\"n\">toppings</span><span class=\"o\">=</span><span class=\"n\">toppings</span><span class=\"p\">,</span> <span class=\"n\">size</span><span class=\"o\">=</span><span class=\"n\">size</span><span class=\"p\">)</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n<p>同期・非同期いずれのレシーバーも、呼び出し時に <code class=\"docutils literal notranslate\"><span class=\"pre\">send()</span></code> か <code class=\"docutils literal notranslate\"><span class=\"pre\">asend()</span></code> のどちらを使うかに応じて自動的に適応されます。 <code class=\"docutils literal notranslate\"><span class=\"pre\">asend()</span></code> 経由で呼び出された場合、同期レシーバーは <a class=\"reference internal\" href=\"/ja/6.0/topics/async/#asgiref.sync.sync_to_async\" title=\"asgiref.sync.sync_to_async\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">sync_to_async()</span></code></a> を介して実行されます。逆に <code class=\"docutils literal notranslate\"><span class=\"pre\">send()</span></code> 経由で呼び出された場合、非同期レシーバーは <a class=\"reference internal\" href=\"/ja/6.0/topics/async/#asgiref.sync.async_to_sync\" title=\"asgiref.sync.async_to_sync\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">async_to_sync()</span></code></a> を介して実行されます。 <a class=\"reference internal\" href=\"/ja/6.0/topics/async/#async-performance\"><span class=\"std std-ref\">ミドルウェアの場合</span></a> と同様、この適応にはわずかなパフォーマンスコストが発生します。 <code class=\"docutils literal notranslate\"><span class=\"pre\">send()</span></code> または <code class=\"docutils literal notranslate\"><span class=\"pre\">asend()</span></code> の内部で同期・非同期の呼び出しスタイルを切り替える回数を減らすため、実行前にレシーバーは「同期か非同期か」でグループ分けされます。その結果、同期レシーバーより前に登録された非同期レシーバーが後に実行されることがあります。さらに、非同期レシーバーは <code class=\"docutils literal notranslate\"><span class=\"pre\">asyncio.gather()</span></code> を用いて並行実行されます。</p>\n<p>非同期のリクエスト/レスポンス・サイクル以外のすべての組み込みシグナルは <a class=\"reference internal\" href=\"#django.dispatch.Signal.send\" title=\"django.dispatch.Signal.send\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">Signal.send()</span></code></a> を使ってディスパッチされます。</p>\n</section>\n</section>\n<section id=\"disconnecting-signals\">\n<h2>シグナルを切断する<a class=\"heading-anchor\" href=\"#disconnecting-signals\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.dispatch.Signal.disconnect\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">Signal.</span></span><span class=\"sig-name descname\"><span class=\"pre\">disconnect</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">receiver</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">sender</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">dispatch_uid</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.dispatch.Signal.disconnect\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>シグナルからレシーバーを切断するには <a class=\"reference internal\" href=\"#django.dispatch.Signal.disconnect\" title=\"django.dispatch.Signal.disconnect\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">Signal.disconnect()</span></code></a> を呼び出します。引数は <a class=\"reference internal\" href=\"#django.dispatch.Signal.connect\" title=\"django.dispatch.Signal.connect\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">Signal.connect()</span></code></a> の説明と同じです。このメソッドは、レシーバが切断された場合は <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> を、切断されなかった場合は <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> を返します。<code class=\"docutils literal notranslate\"><span class=\"pre\">sender</span></code> が <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;app</span> <span class=\"pre\">label&gt;.&lt;model&gt;</span></code> への遅延参照として渡された場合、このメソッドは常に <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> を返します。</p>\n<p>引数 <code class=\"docutils literal notranslate\"><span class=\"pre\">receiver</span></code> は、切断する登録済みのレシーバを指定します。レシーバを識別するために <code class=\"docutils literal notranslate\"><span class=\"pre\">dispatch_uid</span></code> を使用する場合は <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> を指定します。</p>\n</section>","rootId":"module-django.dispatch","toc":[{"title":"シグナルを待ち受ける","anchor":"listening-to-signals","children":[{"title":"レシーバ関数","anchor":"receiver-functions","children":[]},{"title":"レシーバ関数に接続する","anchor":"connecting-receiver-functions","children":[]},{"title":"特定の送信者によって送られたシグナルに接続する","anchor":"connecting-to-signals-sent-by-specific-senders","children":[]},{"title":"重複したシグナルを防止する","anchor":"preventing-duplicate-signals","children":[]}]},{"title":"シグナルの定義と送信","anchor":"defining-and-sending-signals","children":[{"title":"シグナルを定義する","anchor":"defining-signals","children":[]},{"title":"シグナルを送信する","anchor":"sending-signals","children":[]}]},{"title":"シグナルを切断する","anchor":"disconnecting-signals","children":[]}],"breadcrumbs":[{"docname":"topics/index","title":"Django を使う","url":"/ja/6.0/topics/"}],"prev":{"docname":"topics/settings","title":"Djangoの設定","url":"/ja/6.0/topics/settings/"},"next":{"docname":"topics/checks","title":"システムチェックフレームワーク","url":"/ja/6.0/topics/checks/"},"formats":{"html":"/ja/6.0/topics/signals/","markdown":"/ja/6.0/topics/signals.md","json":"/ja/6.0/topics/signals.json"},"source":"https://github.com/django/django/blob/stable/6.0.x/docs/topics/signals.txt","official":"https://docs.djangoproject.com/ja/6.0/topics/signals/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0","1.11","1.10","1.9"],"inLocales":["en","sv","zh-hans","ga","fr","ja","id","it","pt-br","ko","es","el","pl"]}