{"title":"信号","version":"3.1","locale":"zh-hans","docname":"topics/signals","url":"/zh-hans/3.1/topics/signals/","canonical":"https://djangodocs.dev/zh-hans/3.1/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 包含一个“信号调度器”，它帮助已解藕的应用程序在框架中的其它地方发生操作时可以得到通知。简而言之，信号允许某些 <em>发送器</em> 通知一组 <em>接收器</em> 某些操作已经发生。当许多代码段可能对同一事件感兴趣时，它们特别有用。</p>\n<p>Django 提供了 <a class=\"reference internal\" href=\"/zh-hans/3.1/ref/signals/\"><span class=\"doc\">内置信号集</span></a> 使用户代码能够获得 Django 自身某些操作的通知。其中包括一些有用的通知：</p>\n<ul>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/3.1/ref/signals/#django.db.models.signals.pre_save\" title=\"django.db.models.signals.pre_save\"><code class=\"xref py py-data docutils literal notranslate\">django.db.models.signals.pre_save</code></a> &amp;\n<a class=\"reference internal\" href=\"/zh-hans/3.1/ref/signals/#django.db.models.signals.post_save\" title=\"django.db.models.signals.post_save\"><code class=\"xref py py-data docutils literal notranslate\">django.db.models.signals.post_save</code></a></p>\n<p>一个模型的 <a class=\"reference internal\" href=\"/zh-hans/3.1/ref/models/instances/#django.db.models.Model.save\" title=\"django.db.models.Model.save\"><code class=\"xref py py-meth docutils literal notranslate\">save()</code></a> 方法被调用之前或之后发出。</p>\n</li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/3.1/ref/signals/#django.db.models.signals.pre_delete\" title=\"django.db.models.signals.pre_delete\"><code class=\"xref py py-data docutils literal notranslate\">django.db.models.signals.pre_delete</code></a> &amp;\n<a class=\"reference internal\" href=\"/zh-hans/3.1/ref/signals/#django.db.models.signals.post_delete\" title=\"django.db.models.signals.post_delete\"><code class=\"xref py py-data docutils literal notranslate\">django.db.models.signals.post_delete</code></a></p>\n<p>一个模型的 <a class=\"reference internal\" href=\"/zh-hans/3.1/ref/models/instances/#django.db.models.Model.delete\" title=\"django.db.models.Model.delete\"><code class=\"xref py py-meth docutils literal notranslate\">delete()</code></a> 方法或查询结果集的 <a class=\"reference internal\" href=\"/zh-hans/3.1/ref/models/querysets/#django.db.models.query.QuerySet.delete\" title=\"django.db.models.query.QuerySet.delete\"><code class=\"xref py py-meth docutils literal notranslate\">delete()</code></a> 方法被调用之前或之后发出。</p>\n</li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/3.1/ref/signals/#django.db.models.signals.m2m_changed\" title=\"django.db.models.signals.m2m_changed\"><code class=\"xref py py-data docutils literal notranslate\">django.db.models.signals.m2m_changed</code></a></p>\n<p>一个模型的 <a class=\"reference internal\" href=\"/zh-hans/3.1/ref/models/fields/#django.db.models.ManyToManyField\" title=\"django.db.models.ManyToManyField\"><code class=\"xref py py-class docutils literal notranslate\">ManyToManyField</code></a> 更改后发出。</p>\n</li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/3.1/ref/signals/#django.core.signals.request_started\" title=\"django.core.signals.request_started\"><code class=\"xref py py-data docutils literal notranslate\">django.core.signals.request_started</code></a> &amp;\n<a class=\"reference internal\" href=\"/zh-hans/3.1/ref/signals/#django.core.signals.request_finished\" title=\"django.core.signals.request_finished\"><code class=\"xref py py-data docutils literal notranslate\">django.core.signals.request_finished</code></a></p>\n<p>Django 发起或结束一个 HTTP 请求后发出。</p>\n</li>\n</ul>\n<p>查看 <a class=\"reference internal\" href=\"/zh-hans/3.1/ref/signals/\"><span class=\"doc\">内置信号文档</span></a> 以获取每个信号的完整列表和说明。</p>\n<p>你还可以 <a class=\"reference internal\" href=\"#defining-and-sending-signals\">定义和发送自定义信号</a>；见下文。</p>\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\">Signal.connect()</code></a> 方法注册一个 <em>接收器</em> 函数。当发送信号时调用接收器。信号的所有接收器函数都按照注册时的顺序一个接一个调用。</p>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.dispatch.Signal.connect\">\n<span class=\"sig-prename descclassname\">Signal.</span><span class=\"sig-name descname\">connect</span><span class=\"sig-paren\">(</span><em class=\"sig-param\">receiver</em>, <em class=\"sig-param\">sender<span class=\"o\">=</span><span class=\"default_value\">None</span></em>, <em class=\"sig-param\">weak<span class=\"o\">=</span><span class=\"default_value\">True</span></em>, <em class=\"sig-param\">dispatch_uid<span class=\"o\">=</span><span class=\"default_value\">None</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> -- 将连接到此信号的回调函数。查看 <span class=\"xref std std-ref\">接收器函数</span> 获取更多信息。</p></li>\n<li><p><strong>sender</strong> -- 指定要从其接收信号的特定发送方。查看 <span class=\"xref std std-ref\">连接到特定信号</span> 获取更多信息。</p></li>\n<li><p><strong>weak</strong> -- Django 默认将信号处理程序存储为弱引用。因此，如果你的接收器是本地函数，则可能会对其进行垃圾回收。要防止这种情况发生，当你要调用 <code class=\"docutils literal notranslate\">connect()</code> 方法时请传入 <code class=\"docutils literal notranslate\">weak=False</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=\"/zh-hans/3.1/ref/signals/#django.core.signals.request_finished\" title=\"django.core.signals.request_finished\"><code class=\"xref py py-data docutils literal notranslate\">request_finished</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=\"nf\">my_callback</span><span class=\"p\">(</span>sender<span class=\"p\">,</span> <span class=\"o\">**</span>kwargs<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\">sender</code> 参数以及关键字参数 (<code class=\"docutils literal notranslate\">**kwargs</code>)；所有信号处理程序都必须接受这些参数。</p>\n<p><a class=\"reference internal\" href=\"#connecting-to-signals-sent-by-specific-senders\">稍后</a> 我们将讨论发送器，但现在来看下 <code class=\"docutils literal notranslate\">**kwargs</code> 参数。所有信号都发送关键字参数，并且可以随时更改这些关键字参数。在接收 <a class=\"reference internal\" href=\"/zh-hans/3.1/ref/signals/#django.core.signals.request_finished\" title=\"django.core.signals.request_finished\"><code class=\"xref py py-data docutils literal notranslate\">request_finished</code></a> 信号时，该信号没有发送任何参数，这意味着我们可能会试图将我们的信号处理程序写成 <code class=\"docutils literal notranslate\">my_callback(sender)</code>。</p>\n<p>这是错误的——事实上，如果这样做，Django 将抛出一个错误。这是因为在任何时候，参数都可能被添加到信号中，而你的接收器必须能够处理这些新的参数。</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>有两种方法可以将接收器连接到信号。你可以选择手动连接线路：</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=\"nn\">django.core.signals</span> <span class=\"kn\">import</span> request_finished\n\nrequest_finished<span class=\"o\">.</span>connect<span class=\"p\">(</span>my_callback<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\">receiver()</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\">receiver</span><span class=\"sig-paren\">(</span><em class=\"sig-param\">signal</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\"><p><strong>signal</strong> -- 一个用于连接函数的信号或包含多个信号的列表。</p>\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=\"nn\">django.core.signals</span> <span class=\"kn\">import</span> request_finished\n<span class=\"kn\">from</span> <span class=\"nn\">django.dispatch</span> <span class=\"kn\">import</span> receiver\n\n<span class=\"nd\">@receiver</span><span class=\"p\">(</span>request_finished<span class=\"p\">)</span>\n<span class=\"k\">def</span> <span class=\"nf\">my_callback</span><span class=\"p\">(</span>sender<span class=\"p\">,</span> <span class=\"o\">**</span>kwargs<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\">my_callback</code> 函数将在每次请求完成时被调用。</p>\n<aside class=\"admonition-where-should-this-code-live admonition\" role=\"note\">\n<p class=\"admonition-title\">我的代码该放在哪？</p>\n<p>严格来说，信号处理和注册的代码可以放在任何你喜欢的地方，但是推荐避免放在应用程序的根目录和 <code class=\"docutils literal notranslate\">models</code> 模块内以尽量减少导入代码的副作用。</p>\n<p>在实践中，信号处理程序通常定义在与之相关的应用程序的 <code class=\"docutils literal notranslate\">signals</code> 子模块中。信号接收器在你应用程序配置类的 <a class=\"reference internal\" href=\"/zh-hans/3.1/ref/applications/#django.apps.AppConfig.ready\" title=\"django.apps.AppConfig.ready\"><code class=\"xref py py-meth docutils literal notranslate\">ready()</code></a> 方法中连接。如果你使用 <a class=\"reference internal\" href=\"#django.dispatch.receiver\" title=\"django.dispatch.receiver\"><code class=\"xref py py-func docutils literal notranslate\">receiver()</code></a> 装饰器，在 <a class=\"reference internal\" href=\"/zh-hans/3.1/ref/applications/#django.apps.AppConfig.ready\" title=\"django.apps.AppConfig.ready\"><code class=\"xref py py-meth docutils literal notranslate\">ready()</code></a> 中导入 <code class=\"docutils literal notranslate\">signals</code> 子模块。</p>\n</aside>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p><a class=\"reference internal\" href=\"/zh-hans/3.1/ref/applications/#django.apps.AppConfig.ready\" title=\"django.apps.AppConfig.ready\"><code class=\"xref py py-meth docutils literal notranslate\">ready()</code></a> 方法在测试过程中可能会多次执行，因此你可能需要 <a class=\"reference internal\" href=\"#preventing-duplicate-signals\"><span class=\"std std-ref\">防止重复信号</span></a>，尤其是当您计划在测试中发送信号时。</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=\"/zh-hans/3.1/ref/signals/#django.db.models.signals.pre_save\" title=\"django.db.models.signals.pre_save\"><code class=\"xref py py-data docutils literal notranslate\">django.db.models.signals.pre_save</code></a> 在模型保存之前发送的信号。大多数时候，你不需要知道 <em>任何</em> 模型何时被保存——只需要知道某个 <em>特定</em> 模型何时被保存。</p>\n<p>在这些情况下，您可以注册以接收仅由特定发送者发送的信号。在接收 <a class=\"reference internal\" href=\"/zh-hans/3.1/ref/signals/#django.db.models.signals.pre_save\" title=\"django.db.models.signals.pre_save\"><code class=\"xref py py-data docutils literal notranslate\">django.db.models.signals.pre_save</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=\"nn\">django.db.models.signals</span> <span class=\"kn\">import</span> pre_save\n<span class=\"kn\">from</span> <span class=\"nn\">django.dispatch</span> <span class=\"kn\">import</span> receiver\n<span class=\"kn\">from</span> <span class=\"nn\">myapp.models</span> <span class=\"kn\">import</span> MyModel\n\n\n<span class=\"nd\">@receiver</span><span class=\"p\">(</span>pre_save<span class=\"p\">,</span> sender<span class=\"o\">=</span>MyModel<span class=\"p\">)</span>\n<span class=\"k\">def</span> <span class=\"nf\">my_handler</span><span class=\"p\">(</span>sender<span class=\"p\">,</span> <span class=\"o\">**</span>kwargs<span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\">my_handler</code> 函数将仅在 <code class=\"docutils literal notranslate\">MyModel</code> 实例保存后被调用。</p>\n<p>不同的信号使用不同的对象作为它们的发送者；你需要查阅 <a class=\"reference internal\" href=\"/zh-hans/3.1/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>在某些情况下，连接接收器到信号的代码可能被执行多次。这可能会导致接收器函数被注册多次，因此对于一个信号事件调用同样多次。例如，<a class=\"reference internal\" href=\"/zh-hans/3.1/ref/applications/#django.apps.AppConfig.ready\" title=\"django.apps.AppConfig.ready\"><code class=\"xref py py-meth docutils literal notranslate\">ready()</code></a> 方法在测试期间可能被多次执行。更普遍的是，在项目的任何地方导入定义信号的模块都会发生这种情况，因为信号注册的运行次数与导入的次数相同。</p>\n<p>如果此行为会产生问题（例如在保存模型时使用信号发送电子邮件），则传递一个唯一标识符作为 <code class=\"docutils literal notranslate\">dispatch_uid</code> 参数来标识接收方函数。这个标识符通常是一个字符串，尽管任何可散列对象都可以。最终的结果是，对于每个唯一的 <code class=\"docutils literal notranslate\">dispatch_uid</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=\"nn\">django.core.signals</span> <span class=\"kn\">import</span> request_finished\n\nrequest_finished<span class=\"o\">.</span>connect<span class=\"p\">(</span>my_callback<span class=\"p\">,</span> dispatch_uid<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<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\" role=\"note\">\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\">class</span> </em><span class=\"sig-name descname\">Signal</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\">django.dispatch.Signal</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=\"nn\">django.dispatch</span>\n\npizza_done <span class=\"o\">=</span> django<span class=\"o\">.</span>dispatch<span class=\"o\">.</span>Signal<span class=\"p\">()</span>\n</code></pre></div>\n<p>这声明了一个 <code class=\"docutils literal notranslate\">pizza_done</code> 信号。</p>\n</section>\n<section id=\"sending-signals\">\n<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 中有两种发送信号的方法。</p>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.dispatch.Signal.send\">\n<span class=\"sig-prename descclassname\">Signal.</span><span class=\"sig-name descname\">send</span><span class=\"sig-paren\">(</span><em class=\"sig-param\">sender</em>, <em class=\"sig-param\"><span class=\"o\">**</span>kwargs</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\">Signal.</span><span class=\"sig-name descname\">send_robust</span><span class=\"sig-paren\">(</span><em class=\"sig-param\">sender</em>, <em class=\"sig-param\"><span class=\"o\">**</span>kwargs</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>要发送信号，调用 <a class=\"reference internal\" href=\"#django.dispatch.Signal.send\" title=\"django.dispatch.Signal.send\"><code class=\"xref py py-meth docutils literal notranslate\">Signal.send()</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\">Signal.send_robust()</code></a>。你必须提供 <code class=\"docutils literal notranslate\">sender</code> 参数（大多数情况下是一个类），还可以根据需要提供任意多个其他关键字参数。</p>\n<p>例如，发送 <code class=\"docutils literal notranslate\">pizza_done</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=\"nc\">PizzaStore</span><span class=\"p\">:</span>\n    <span class=\"o\">...</span>\n\n    <span class=\"k\">def</span> <span class=\"nf\">send_pizza</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> toppings<span class=\"p\">,</span> size<span class=\"p\">):</span>\n        pizza_done<span class=\"o\">.</span>send<span class=\"p\">(</span>sender<span class=\"o\">=</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"vm\">__class__</span><span class=\"p\">,</span> toppings<span class=\"o\">=</span>toppings<span class=\"p\">,</span> size<span class=\"o\">=</span>size<span class=\"p\">)</span>\n        <span class=\"o\">...</span>\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\">send()</code> 和 <code class=\"docutils literal notranslate\">send_robust()</code> 都返回一个元组对列表 <code class=\"docutils literal notranslate\">[(receiver, response), ... ]</code>，表示被调用的接收器函数及其响应值的列表。</p>\n<p><code class=\"docutils literal notranslate\">send()</code> 和 <code class=\"docutils literal notranslate\">send_robust()</code> 在处理接收器函数所引发异常的方式上有所不同。 <code class=\"docutils literal notranslate\">send()</code> <em>不</em> 捕获接收器引起的任何异常；它只是允许错误传播。因此，并非所有的接收器都会在出现错误时被通知信号。</p>\n<p><code class=\"docutils literal notranslate\">send_robust()</code> 捕获从 Python的 <code class=\"docutils literal notranslate\">Exception</code> 类派生的所有错误，并确保所有接收器都收到信号通知。如果发生错误，将在引发错误的接收器的元组对中返回错误实例。</p>\n<p>回溯出现在调用 <code class=\"docutils literal notranslate\">send_robust()</code> 时返回的错误中的 <code class=\"docutils literal notranslate\">__traceback__</code> 属性中。</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\">Signal.</span><span class=\"sig-name descname\">disconnect</span><span class=\"sig-paren\">(</span><em class=\"sig-param\">receiver<span class=\"o\">=</span><span class=\"default_value\">None</span></em>, <em class=\"sig-param\">sender<span class=\"o\">=</span><span class=\"default_value\">None</span></em>, <em class=\"sig-param\">dispatch_uid<span class=\"o\">=</span><span class=\"default_value\">None</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\">Signal.disconnect()</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\">Signal.connect()</code></a> 描述。该方法成功断开连接返回 <code class=\"docutils literal notranslate\">True</code> 否则返回 <code class=\"docutils literal notranslate\">False</code> 。</p>\n<p><code class=\"docutils literal notranslate\">receiver</code> 参数表明要断开的接收器。它可以是 <code class=\"docutils literal notranslate\">None</code> 如果 <code class=\"docutils literal notranslate\">dispatch_uid</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":"/zh-hans/3.1/topics/"}],"prev":{"docname":"topics/settings","title":"Django 配置","url":"/zh-hans/3.1/topics/settings/"},"next":{"docname":"topics/checks","title":"系统检查框架","url":"/zh-hans/3.1/topics/checks/"},"formats":{"html":"/zh-hans/3.1/topics/signals/","markdown":"/zh-hans/3.1/topics/signals.md","json":"/zh-hans/3.1/topics/signals.json"},"source":"https://github.com/django/django/blob/stable/3.1.x/docs/topics/signals.txt","official":"https://docs.djangoproject.com/zh-hans/3.1/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"],"inLocales":["en","zh-hans","fr","ja","id","pt-br","ko","es","el","pl"]}