{"title":"Signaux","version":"6.1","locale":"fr","docname":"topics/signals","url":"/fr/6.1/topics/signals/","canonical":"https://djangodocs.dev/fr/6.1/topics/signals/","summary":"Django contient un « distributeur de signaux » qui permet aux applications découplées de pouvoir plus facilement être averties quand des actions se…","html":"<span id=\"signals\"></span><h1>Signaux<a class=\"heading-anchor\" href=\"#module-django.dispatch\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>Django contient un « distributeur de signaux » qui permet aux applications découplées de pouvoir plus facilement être averties quand des actions se produisent ailleurs dans un projet. En résumé, les signaux permettent à certains <em>expéditeurs</em> d’avertir un ensemble de <em>destinataires</em> qu’une action a eu lieu. Ils sont particulièrement utiles lorsque beaucoup de parties de code peuvent être intéressées aux mêmes événements.</p>\n<p>Par exemple, une application tierce peut s’inscrire pour être avertie des modifications de réglages</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.apps</span> <span class=\"kn\">import</span> AppConfig\n<span class=\"kn\">from</span> <span class=\"nn\">django.core.signals</span> <span class=\"kn\">import</span> setting_changed\n\n\n<span class=\"k\">def</span> <span class=\"nf\">my_receiver</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;Setting changed!&quot;</span><span class=\"p\">)</span>\n\n\n<span class=\"k\">class</span> <span class=\"nc\">MyAppConfig</span><span class=\"p\">(</span>AppConfig<span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n\n    <span class=\"k\">def</span> <span class=\"nf\">ready</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        setting_changed<span class=\"o\">.</span>connect<span class=\"p\">(</span>my_receiver<span class=\"p\">)</span>\n</code></pre></div>\n<p>Les <a class=\"reference internal\" href=\"/fr/6.1/ref/signals/\"><span class=\"doc\">signaux propres à Django</span></a> permettent à du code utilisateur d’être averti de certaines actions.</p>\n<p>Vous pouvez également définir et envoyer vos propres signaux personnalisés. Voir <a class=\"reference internal\" href=\"#defining-and-sending-signals\"><span class=\"std std-ref\">Définition et envoi de signaux</span></a> ci-dessous.</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Avertissement</p>\n<p>Les signaux donnent une apparence de couplage faible, mais ils peuvent rapidement amener à du code difficile à comprendre, à ajuster et à déboguer.</p>\n<p>Partout où c’est possible, vous devriez choisir des appels directs au code à exécuter, plutôt que par la distribution de signaux.</p>\n</aside>\n<section id=\"listening-to-signals\">\n<h2>Écoute de signaux<a class=\"heading-anchor\" href=\"#listening-to-signals\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Pour recevoir un signal, inscrivez une fonction <em>réceptrice</em> en utilisant la méthode <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>. Cette fonction sera appelée au moment où le signal est envoyé. Toutes les fonctions réceptrices d’un signal sont appelées consécutivement dans l’ordre où elles ont été inscrites.</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\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><dl class=\"field-list simple\">\n<dt class=\"field-odd\">Paramètres<span class=\"colon\">:</span></dt>\n<dd class=\"field-odd\"><ul class=\"simple\">\n<li><p><strong>receiver</strong> – La fonction réceptrice qui sera connectée à ce signal. Voir <a class=\"reference internal\" href=\"#receiver-functions\"><span class=\"std std-ref\">Fonctions réceptrices</span></a> pour plus d’informations.</p></li>\n<li><p><strong>sender</strong> – Indique un expéditeur particulier duquel recevoir les signaux. Voir <a class=\"reference internal\" href=\"#connecting-to-specific-signals\"><span class=\"std std-ref\">Connexion aux signaux envoyés par des expéditeurs spécifiques</span></a> pour plus d’informations.</p></li>\n<li><p><strong>weak</strong> – Django stores signal receivers as weak references by\ndefault. Thus, if your receiver is a local function, it may be\ngarbage collected. To prevent this, pass <code class=\"docutils literal notranslate\">weak=False</code> when you call\nthe signal’s <code class=\"docutils literal notranslate\">connect()</code> method.</p></li>\n<li><p><strong>dispatch_uid</strong> – Un identifiant unique pour un récepteur de signal afin d’éviter que certains signaux puissent être envoyés à double. Voir <a class=\"reference internal\" href=\"#preventing-duplicate-signals\"><span class=\"std std-ref\">Prévention des signaux dupliqués</span></a> pour plus d’informations.</p></li>\n</ul>\n</dd>\n</dl>\n</dd></dl>\n\n<p>Voyons comment ça fonctionne en inscrivant un signal qui sera appelé à la fin de chaque requête HTTP. Nous allons nous connecter au signal <a class=\"reference internal\" href=\"/fr/6.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>Fonctions réceptrices<a class=\"heading-anchor\" href=\"#receiver-functions\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Tout d’abord, nous devons définir une fonction réceptrice. Celle-ci peut être n’importe quelle fonction ou méthode 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_receiver</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>Notice that the function takes a <code class=\"docutils literal notranslate\">sender</code> argument, along with wildcard\nkeyword arguments (<code class=\"docutils literal notranslate\">**kwargs</code>); all signal receivers must take these\narguments.</p>\n<p>We’ll look at senders <a class=\"reference internal\" href=\"#connecting-to-specific-signals\"><span class=\"std std-ref\">a bit later</span></a>, but\nright now look at the <code class=\"docutils literal notranslate\">**kwargs</code> argument. All signals send keyword\narguments, and may change those keyword arguments at any time. In the case of\n<a class=\"reference internal\" href=\"/fr/6.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>, it’s documented as sending no\narguments, which means we might be tempted to write our signal handling as\n<code class=\"docutils literal notranslate\">my_receiver(sender)</code>.</p>\n<p>Ce serait une erreur. En fait, Django génère une exception dans ce cas, parce que l’on doit s’attendre à ce que de nouveaux paramètres soient ajoutés dans le temps et la fonction réceptrice doit être capable d’accepter ces nouveaux paramètres.</p>\n<p>Les récepteurs peuvent aussi être des fonctions asynchrones, avec la même signature mais déclarées comme <code class=\"docutils literal notranslate\">async def</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=\"nf\">my_receiver</span><span class=\"p\">(</span>sender<span class=\"p\">,</span> <span class=\"o\">**</span>kwargs<span class=\"p\">):</span>\n    <span class=\"k\">await</span> asyncio<span class=\"o\">.</span>sleep<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>Les signaux peuvent être envoyés de manière synchrone ou asynchrone, et les récepteurs s’adapteront automatiquement au style d’appel approprié. Voir <a class=\"reference internal\" href=\"#sending-signals\"><span class=\"std std-ref\">envoi de signaux</span></a> pour plus d’informations.</p>\n</section>\n<section id=\"connecting-receiver-functions\">\n<span id=\"id2\"></span><h3>Connexion des fonctions réceptrices<a class=\"heading-anchor\" href=\"#connecting-receiver-functions\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Il y a deux façons de connecter une fonction réceptrice à un signal. Vous pouvez choisir l’option de la connexion manuelle :</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_receiver<span class=\"p\">)</span>\n</code></pre></div>\n<p>L’autre possibilité est d’utiliser le décorateur <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>, <em class=\"sig-param\"><span class=\"o\">**</span>kwargs</em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.dispatch.receiver\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><dl class=\"field-list simple\">\n<dt class=\"field-odd\">Paramètres<span class=\"colon\">:</span></dt>\n<dd class=\"field-odd\"><ul class=\"simple\">\n<li><p><strong>signal</strong> – Un signal ou une liste de signaux auxquels connecter la fonction.</p></li>\n<li><p><strong>kwargs</strong> – Autres paramètres nommés arbitraires à passer à la <a class=\"reference internal\" href=\"#receiver-functions\"><span class=\"std std-ref\">fonction</span></a>.</p></li>\n</ul>\n</dd>\n</dl>\n</dd></dl>\n\n<p>Voici comment faire la connexion avec le décorateur :</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\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_receiver</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>Now, our <code class=\"docutils literal notranslate\">my_receiver</code> function will be called each time a request finishes.</p>\n<aside class=\"admonition-where-should-this-code-live admonition\" role=\"note\">\n<p class=\"admonition-title\">À quel endroit ce code devrait-il se trouver ?</p>\n<p>Strictement parlant, le code du signal et le code d’inscription peuvent se trouver n’importe où, même s’il est recommandé d’éviter le module racine de l’application et son module <code class=\"docutils literal notranslate\">models</code> pour minimiser les effets de bord de l’importation du code.</p>\n<p>In practice, signal receivers are usually defined in a <code class=\"docutils literal notranslate\">signals</code>\nsubmodule of the application they relate to. Signal receivers are\nconnected in the <a class=\"reference internal\" href=\"/fr/6.1/ref/applications/#django.apps.AppConfig.ready\" title=\"django.apps.AppConfig.ready\"><code class=\"xref py py-meth docutils literal notranslate\">ready()</code></a> method of your\napplication <a class=\"reference internal\" href=\"/fr/6.1/ref/applications/#configuring-applications-ref\"><span class=\"std std-ref\">configuration class</span></a>. If\nyou’re using the <a class=\"reference internal\" href=\"#django.dispatch.receiver\" title=\"django.dispatch.receiver\"><code class=\"xref py py-func docutils literal notranslate\">receiver()</code></a> decorator, import the <code class=\"docutils literal notranslate\">signals</code>\nsubmodule inside <a class=\"reference internal\" href=\"/fr/6.1/ref/applications/#django.apps.AppConfig.ready\" title=\"django.apps.AppConfig.ready\"><code class=\"xref py py-meth docutils literal notranslate\">ready()</code></a>, this will implicitly\nconnect signal receivers:</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.apps</span> <span class=\"kn\">import</span> AppConfig\n<span class=\"kn\">from</span> <span class=\"nn\">django.core.signals</span> <span class=\"kn\">import</span> request_finished\n\n\n<span class=\"k\">class</span> <span class=\"nc\">MyAppConfig</span><span class=\"p\">(</span>AppConfig<span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n\n    <span class=\"k\">def</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 receivers decorated with @receiver.</span>\n        <span class=\"kn\">from</span> <span class=\"nn\">.</span> <span class=\"kn\">import</span> signals\n\n        <span class=\"c1\"># Explicitly connect a signal handler.</span>\n        request_finished<span class=\"o\">.</span>connect<span class=\"p\">(</span>signals<span class=\"o\">.</span>my_receiver<span class=\"p\">)</span>\n</code></pre></div>\n</aside>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>Il est possible que la méthode <a class=\"reference internal\" href=\"/fr/6.1/ref/applications/#django.apps.AppConfig.ready\" title=\"django.apps.AppConfig.ready\"><code class=\"xref py py-meth docutils literal notranslate\">ready()</code></a> soit exécutée plus d’une fois durant les tests. Par conséquent, il est préférable <a class=\"reference internal\" href=\"#preventing-duplicate-signals\"><span class=\"std std-ref\">d’empêcher la duplication des signaux</span></a>, si votre récepteur est une méthode liée à une instance qui pourrait être recréée.</p>\n</aside>\n</section>\n<section id=\"connecting-to-signals-sent-by-specific-senders\">\n<span id=\"connecting-to-specific-signals\"></span><h3>Connexion aux signaux envoyés par des expéditeurs spécifiques<a class=\"heading-anchor\" href=\"#connecting-to-signals-sent-by-specific-senders\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Certains signaux sont envoyés de nombreuses fois, mais vous n’êtes pas toujours intéressé à tous les recevoir. Par exemple, considérez le signal <a class=\"reference internal\" href=\"/fr/6.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> envoyé avant chaque enregistrement de modèle. La plupart du temps, vous n’avez pas besoin de savoir quand <em>chaque</em> modèle est enregistré, mais seulement pour un modèle <em>spécifique</em>.</p>\n<p>Dans ces situations, vous pouvez inscrire une fonction pour qu’elle ne reçoive les signaux que de certains expéditeurs. Dans le cas de <a class=\"reference internal\" href=\"/fr/6.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>, l’expéditeur sera la classe du modèle en cours d’enregistrement, il est donc possible d’indiquer que vous ne voulez recevoir que les signaux envoyés par certains modèles :</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> <span class=\"o\">...</span>\n</code></pre></div>\n<p>La fonction <code class=\"docutils literal notranslate\">my_handler</code> ne sera appelée que lors de l’enregistrement d’une instance de <code class=\"docutils literal notranslate\">MyModel</code>.</p>\n<p>Différents signaux utilisent différents objets comme expéditeurs ; il s’agit de consulter la <a class=\"reference internal\" href=\"/fr/6.1/ref/signals/\"><span class=\"doc\">documentation des signaux intégrés</span></a> pour plus de détails sur chaque signal.</p>\n</section>\n<section id=\"preventing-duplicate-signals\">\n<span id=\"id3\"></span><h3>Prévention des signaux dupliqués<a class=\"heading-anchor\" href=\"#preventing-duplicate-signals\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Lorsque <code class=\"docutils literal notranslate\">dispatch_uid</code> n’est pas fourni, Django identifie chaque récepteur en utilisant son identité d’objet Python et l’inscrit une seule fois. Pour les fonctions de niveau module, les méthodes statiques et les méthodes de classes, l’identité est stable, ce qui fait qu’une connexion du même récepteur à plusieurs reprises n’a aucun effet :</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_handler</span><span class=\"p\">(</span>sender<span class=\"p\">,</span> <span class=\"o\">**</span>kwargs<span class=\"p\">):</span> <span class=\"o\">...</span>\n\n\nmy_signal<span class=\"o\">.</span>connect<span class=\"p\">(</span>my_handler<span class=\"p\">)</span>  <span class=\"c1\"># Running this code again is a no-op.</span>\n</code></pre></div>\n<p>Les méthodes liées qui acceptent un argument <code class=\"docutils literal notranslate\">self</code> sont un cas différent. Leur identité est liée à une instance spécifique, ce qui fait que la connexion d’une même méthode mais d’une nouvelle instance va l’inscrire comme nouveau récepteur :</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\">connect_signals</span><span class=\"p\">():</span>\n    backend <span class=\"o\">=</span> Backend<span class=\"p\">()</span>\n    my_signal<span class=\"o\">.</span>connect<span class=\"p\">(</span>backend<span class=\"o\">.</span>my_handler<span class=\"p\">)</span>  <span class=\"c1\"># A distinct receiver.</span>\n\n\nconnect_signals<span class=\"p\">()</span>  <span class=\"c1\"># Running this code again registers another receiver.</span>\n</code></pre></div>\n<p>Lors de l’utilisation d’une méthode liée comme récepteur, plusieurs inscriptions peuvent être évitées en fournissant un <code class=\"docutils literal notranslate\">dispatch_uid</code> unique. Il s’agit généralement d’une chaîne de caractères, même si n’importe quel objet hachable peut faire l’affaire. Le récepteur ne sera inscrit au signal qu’une seule fois par valeur unique de <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_receiver<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<span id=\"id4\"></span><h2>Définition et envoi de signaux<a class=\"heading-anchor\" href=\"#defining-and-sending-signals\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Les applications peuvent profiter de l’infrastructure des signaux et fournir leurs propres signaux.</p>\n<aside class=\"admonition-when-to-use-custom-signals admonition\" role=\"note\">\n<p class=\"admonition-title\">Quand utiliser des signaux personnalisés</p>\n<p>Les signaux sont des appels de fonctions implicites qui compliquent le débogage. Si l’expéditeur et le destinataire de votre signal personnalisé sont tous deux dans votre projet, il est alors préférable d’utiliser un appel de fonction explicite.</p>\n</aside>\n<section id=\"defining-signals\">\n<h3>Définition de signaux<a class=\"heading-anchor\" href=\"#defining-signals\"><span class=\"visually-hidden\">Lien vers cette rubrique</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\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Tous les signaux sont des instances de <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>Par exemple :</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>Ceci déclare un signal <code class=\"docutils literal notranslate\">pizza_done</code>.</p>\n</section>\n<section id=\"sending-signals\">\n<span id=\"id5\"></span><h3>Envoi de signaux<a class=\"heading-anchor\" href=\"#sending-signals\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Il y a deux façons d’envoyer des signaux dans Django de manière snychrone.</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\">Lien vers cette définition</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\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Les signaux peuvent aussi être envoyés de manière asynchrone.</p>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.dispatch.Signal.asend\">\n<span class=\"sig-prename descclassname\">Signal.</span><span class=\"sig-name descname\">asend</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.asend\"><span class=\"visually-hidden\">Lien vers cette définition</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\">Signal.</span><span class=\"sig-name descname\">asend_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.asend_robust\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Pour envoyer un signal, appelez <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>, <a class=\"reference internal\" href=\"#django.dispatch.Signal.asend\" title=\"django.dispatch.Signal.asend\"><code class=\"xref py py-meth docutils literal notranslate\">await Signal.asend()</code></a>, or <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\">await Signal.asend_robust()</code></a>. Vous devez indiquer l’argument <code class=\"docutils literal notranslate\">sender</code> (qui est une classe la plupart du temps) et vous pouvez ajouter autant d’arguments nommés que vous le souhaitez.</p>\n<p>Par exemple, voici comment envoyer notre signal <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>Les quatre méthodes renvoient uns liste de paires de tuples <code class=\"docutils literal notranslate\">[(récepteur, réponse), ... ]</code> correspondant à la liste des fonctions réceptrices appelées et la valeur de leur réponse.</p>\n<p><code class=\"docutils literal notranslate\">send()</code> diffère de <code class=\"docutils literal notranslate\">send_robust()</code> par la manière dont les exceptions générées par les fonctions réceptrices sont traitées. <code class=\"docutils literal notranslate\">send()</code> n’intercepte <em>aucune</em> exception générée par les récepteurs ; elle laisse simplement les erreurs se propager. Il est donc possible que certains récepteurs ne soient pas notifiés par le signal en cas d’erreur.</p>\n<p><code class=\"docutils literal notranslate\">send_robust()</code> intercepte toutes les erreurs héritant de la classe <code class=\"docutils literal notranslate\">Exception</code> de Python et s’assure que tous les récepteurs soient notifiés par le signal. Si une erreur survient, l’instance d’erreur est renvoyée dans le tuple correspondant au récepteur qui a généré l’erreur.</p>\n<p>Les traces de débogage sont présentes dans l’attribut <code class=\"docutils literal notranslate\">__traceback__</code> des erreurs renvoyées lors des appels à <code class=\"docutils literal notranslate\">send_robust()</code>.</p>\n<p><code class=\"docutils literal notranslate\">asend()</code> est semblable à <code class=\"docutils literal notranslate\">send()</code>, mais il s’agit d’une coroutine qu’il faut appeler par <code class=\"docutils literal notranslate\">await</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=\"nf\">asend_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    <span class=\"k\">await</span> pizza_done<span class=\"o\">.</span>asend<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>Whether synchronous or asynchronous, receivers will be correctly adapted to\nwhether <code class=\"docutils literal notranslate\">send()</code> or <code class=\"docutils literal notranslate\">asend()</code> is used. Synchronous receivers will be\ncalled using <a class=\"reference internal\" href=\"/fr/6.1/topics/async/#asgiref.sync.sync_to_async\" title=\"asgiref.sync.sync_to_async\"><code class=\"xref py py-func docutils literal notranslate\">sync_to_async()</code></a> when invoked via <code class=\"docutils literal notranslate\">asend()</code>. Asynchronous\nreceivers will be called using <a class=\"reference internal\" href=\"/fr/6.1/topics/async/#asgiref.sync.async_to_sync\" title=\"asgiref.sync.async_to_sync\"><code class=\"xref py py-func docutils literal notranslate\">async_to_sync()</code></a> when invoked via\n<code class=\"docutils literal notranslate\">send()</code>. Similar to the <a class=\"reference internal\" href=\"/fr/6.1/topics/async/#async-performance\"><span class=\"std std-ref\">case for middleware</span></a>,\nthere is a small performance cost to adapting receivers in this way. Note that\nin order to reduce the number of sync/async calling-style switches within a\n<code class=\"docutils literal notranslate\">send()</code> or <code class=\"docutils literal notranslate\">asend()</code> call, the receivers are grouped by whether or not\nthey are async before being called. This means that an asynchronous receiver\nregistered before a synchronous receiver may be executed after the synchronous\nreceiver. In addition, async receivers are executed concurrently using\n<a class=\"reference external\" href=\"https://docs.python.org/3/library/asyncio-task.html#asyncio.TaskGroup\" title=\"(disponible dans Python v3.14)\"><code class=\"xref py py-class docutils literal notranslate\">asyncio.TaskGroup</code></a>.</p>\n<p>Tous les signaux intégrés à Django, sauf ceux faisant partie du cycle requête-réponse asynchrone, sont envoyés par <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>.</p>\n<aside class=\"version-note version-changed\" data-version=\"6.1\" role=\"note\">\n<p class=\"version-note-title\">Changed in Django 6.1</p><p>In older versions, async receivers were executed via <code class=\"docutils literal notranslate\">asyncio.gather()</code>.</p>\n</aside>\n</section>\n</section>\n<section id=\"disconnecting-signals\">\n<h2>Déconnexion des signaux<a class=\"heading-anchor\" href=\"#disconnecting-signals\"><span class=\"visually-hidden\">Lien vers cette rubrique</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\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Pour déconnecter un récepteur d’un signal, appelez <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>. Les paramètres sont identiques à ceux décrits pour <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>. La méthode renvoie <code class=\"docutils literal notranslate\">True</code> si un récepteur a été déconnecté, sinon <code class=\"docutils literal notranslate\">False</code>. Lorsque <code class=\"docutils literal notranslate\">sender</code> est transmis comme référence différée à <code class=\"docutils literal notranslate\">&lt;app label&gt;.&lt;model&gt;</code>, cette méthode renvoie toujours <code class=\"docutils literal notranslate\">None</code>.</p>\n<p>Le paramètre <code class=\"docutils literal notranslate\">receiver</code> indique le récepteur inscrit qu’il s’agit de déconnecter. Il peut valoir <code class=\"docutils literal notranslate\">None</code> si <code class=\"docutils literal notranslate\">dispatch_uid</code> est utilisé pour identifier le récepteur.</p>\n</section>","rootId":"module-django.dispatch","toc":[{"title":"Écoute de signaux","anchor":"listening-to-signals","children":[{"title":"Fonctions réceptrices","anchor":"receiver-functions","children":[]},{"title":"Connexion des fonctions réceptrices","anchor":"connecting-receiver-functions","children":[]},{"title":"Connexion aux signaux envoyés par des expéditeurs spécifiques","anchor":"connecting-to-signals-sent-by-specific-senders","children":[]},{"title":"Prévention des signaux dupliqués","anchor":"preventing-duplicate-signals","children":[]}]},{"title":"Définition et envoi de signaux","anchor":"defining-and-sending-signals","children":[{"title":"Définition de signaux","anchor":"defining-signals","children":[]},{"title":"Envoi de signaux","anchor":"sending-signals","children":[]}]},{"title":"Déconnexion des signaux","anchor":"disconnecting-signals","children":[]}],"breadcrumbs":[{"docname":"topics/index","title":"Utilisation de Django","url":"/fr/6.1/topics/"}],"prev":{"docname":"topics/settings","title":"Les réglages de Django","url":"/fr/6.1/topics/settings/"},"next":{"docname":"topics/checks","title":"Infrastructure de contrôle du système","url":"/fr/6.1/topics/checks/"},"formats":{"html":"/fr/6.1/topics/signals/","markdown":"/fr/6.1/topics/signals.md","json":"/fr/6.1/topics/signals.json"},"source":"https://github.com/django/django/blob/stable/6.1.x/docs/topics/signals.txt","official":"https://docs.djangoproject.com/fr/6.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","1.11","1.10","1.9"],"inLocales":["en","sv","zh-hans","ga","fr","ja","id","it","pt-br","ko","es","el","pl"]}