{"title":"Gestion du code asynchrone","version":"5.1","locale":"fr","docname":"topics/async","url":"/fr/5.1/topics/async/","canonical":"https://djangodocs.dev/fr/5.1/topics/async/","summary":"Django prend en charge l’écriture de vues asynchrones (« async »), en conjonction avec une pile de requête adaptée pour l’asynchrone, pour autant que vous…","html":"<h1>Gestion du code asynchrone<a class=\"heading-anchor\" href=\"#asynchronous-support\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>Django prend en charge l’écriture de vues asynchrones (« async »), en conjonction avec une pile de requête adaptée pour l’asynchrone, pour autant que vous fonctionniez avec <a class=\"reference internal\" href=\"/fr/5.1/howto/deployment/asgi/\"><span class=\"doc\">ASGI</span></a>. Les vues asynchrones fonctionnent aussi avec WSGI, mais avec des performances moindres et sans possibilité de bénéficier de requêtes de longue durée efficaces.</p>\n<p>Le travail sur la prise en charge de l’asynchrone est toujours en cours sur l’ORM et d’autres parties de Django. Nous espérons en voir le fruit dans de futures publications de Django. Pour le moment, vous pouvez utiliser l’adaptateur <a class=\"reference internal\" href=\"#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> pour interagir avec les parties synchrones de Django. Il existe aussi un vaste choix de bibliothèques Python nativement asynchrones avec lesquelles vous pouvez intégrer votre code.</p>\n<section id=\"async-views\">\n<h2>Vues asynchrones<a class=\"heading-anchor\" href=\"#async-views\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Toute vue peut être déclarée asynchrone en faisant renvoyer une coroutine de sa partie exécutable ; ceci se fait en principe avec <code class=\"docutils literal notranslate\"><span class=\"pre\">async</span> <span class=\"pre\">def</span></code>. Pour une vue basée sur une fonction, cela signifie déclarer la vue entière comme <code class=\"docutils literal notranslate\"><span class=\"pre\">async</span> <span class=\"pre\">def</span></code>. Pour une vue basée sur une classe, cela signifie définir les gestionnaires de méthodes tels que  <code class=\"docutils literal notranslate\"><span class=\"pre\">get()</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">post()</span></code> comme <code class=\"docutils literal notranslate\"><span class=\"pre\">async</span> <span class=\"pre\">def</span></code> (pas la méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">__init__()</span></code> ni <code class=\"docutils literal notranslate\"><span class=\"pre\">as_view()</span></code>).</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>Django utilise <code class=\"docutils literal notranslate\"><span class=\"pre\">asgiref.sync.iscoroutinefunction</span></code> pour tester si la vue est asynchrone ou pas. Si vous implémentez votre propre méthode pour renvoyer une coroutine, prenez soin d’utiliser <code class=\"docutils literal notranslate\"><span class=\"pre\">asgiref.sync.markcoroutinefunction</span></code> pour que cette fonction renvoie <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>.</p>\n</aside>\n<p>Avec un serveur WSGI, les vues asynchrones tournent dans leur propre boucle événementielle unique. Cela veut dire que vous pouvez utiliser sans problème des fonctionnalités asynchrones, telles que des requêtes HTTP asynchrones et concurrentes, mais vous ne bénéficierez pas des avantages d’une pile asynchrone.</p>\n<p>Les bénéfices principaux sont de pouvoir servir des centaines de connexions sans faire appel aux files d’exécutions (threads) Python. Cela vous permet d’utiliser les flux lents et les interrogations lentes (slow streaming, long-polling), et autres techniques semblables pour les réponses.</p>\n<p>Si vous souhaitez exploiter ces possibilités, vous devrez déployer Django en utilisant plutôt un serveur <a class=\"reference internal\" href=\"/fr/5.1/howto/deployment/asgi/\"><span class=\"doc\">ASGI</span></a>.</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Avertissement</p>\n<p>Vous ne pourrez obtenir les bénéfices d’une pile de requête pleinement asynchrone que si <em>aucun intergiciel synchrone</em> n’est chargé dans votre site. Si un intergiciel synchrone est chargé, Django est obligé d’employer un fil d’exécution par requête pour émuler un environnement synchrone de manière sûre.</p>\n<p>Un intergiciel peut être conçu pour prendre en charge à la fois des contextes <a class=\"reference internal\" href=\"/fr/5.1/topics/http/middleware/#async-middleware\"><span class=\"std std-ref\">synchrones et asynchrones</span></a>. Certains intergiciels de Django sont conçus de cette manière, mais pas tous. Pour voir quels sont les intergiciels que Django doit adapter, vous pouvez activer la journalisation de débogage pour le journaliseur <code class=\"docutils literal notranslate\"><span class=\"pre\">django.request</span></code> et observer les messages mentionnant <em>« Asynchronous handler adapted for middleware … »</em>.</p>\n</aside>\n<p>Que ce soit en mode ASGI ou WSGI, vous pouvez toujours exploiter la prise en charge asynchrone de manière sûre pour exécuter du code de manière concurrente plutôt qu’en série. C’est particulièrement pratique lorsqu’on interagit avec des API externes ou des stockages de données.</p>\n<p>Si vous souhaitez appeler une partie de Django qui est encore synchrone, il vous faut l’envelopper dans un appel à <a class=\"reference internal\" href=\"#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>. 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\">from</span><span class=\"w\"> </span><span class=\"nn\">asgiref.sync</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">sync_to_async</span>\n\n<span class=\"n\">results</span> <span class=\"o\">=</span> <span class=\"k\">await</span> <span class=\"n\">sync_to_async</span><span class=\"p\">(</span><span class=\"n\">sync_function</span><span class=\"p\">,</span> <span class=\"n\">thread_sensitive</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)(</span><span class=\"n\">pk</span><span class=\"o\">=</span><span class=\"mi\">123</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Si par accident vous essayez d’appeler une partie de Django qui est purement synchrone à partir d’une vue asynchrone, vous déclencherez la <a class=\"reference internal\" href=\"#async-safety\"><span class=\"std std-ref\">protection de sécurité asynchrone</span></a> de Django qui vise à protéger vos données d’une éventuelle corruption.</p>\n<section id=\"decorators\">\n<h3>Décorateurs<a class=\"heading-anchor\" href=\"#decorators\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<aside class=\"version-note version-added\" data-version=\"5.0\">\n<p class=\"version-note-title\">New in Django 5.0</p></aside>\n<p>Les décorateurs suivants peuvent être utilisés avec des fonctions de vues à la fois synchrones et asynchrones :</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"/fr/5.1/topics/http/decorators/#django.views.decorators.cache.cache_control\" title=\"django.views.decorators.cache.cache_control\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">cache_control()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/5.1/topics/http/decorators/#django.views.decorators.cache.never_cache\" title=\"django.views.decorators.cache.never_cache\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">never_cache()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/5.1/topics/http/decorators/#django.views.decorators.common.no_append_slash\" title=\"django.views.decorators.common.no_append_slash\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">no_append_slash()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/5.1/ref/csrf/#django.views.decorators.csrf.csrf_exempt\" title=\"django.views.decorators.csrf.csrf_exempt\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">csrf_exempt()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/5.1/ref/csrf/#django.views.decorators.csrf.csrf_protect\" title=\"django.views.decorators.csrf.csrf_protect\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">csrf_protect()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/5.1/ref/csrf/#django.views.decorators.csrf.ensure_csrf_cookie\" title=\"django.views.decorators.csrf.ensure_csrf_cookie\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">ensure_csrf_cookie()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/5.1/ref/csrf/#django.views.decorators.csrf.requires_csrf_token\" title=\"django.views.decorators.csrf.requires_csrf_token\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">requires_csrf_token()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/5.1/howto/error-reporting/#django.views.decorators.debug.sensitive_variables\" title=\"django.views.decorators.debug.sensitive_variables\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">sensitive_variables()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/5.1/howto/error-reporting/#django.views.decorators.debug.sensitive_post_parameters\" title=\"django.views.decorators.debug.sensitive_post_parameters\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">sensitive_post_parameters()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/5.1/topics/http/decorators/#django.views.decorators.gzip.gzip_page\" title=\"django.views.decorators.gzip.gzip_page\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">gzip_page()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/5.1/topics/http/decorators/#django.views.decorators.http.condition\" title=\"django.views.decorators.http.condition\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">condition()</span></code></a></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">conditional_page()</span></code></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/5.1/topics/http/decorators/#django.views.decorators.http.etag\" title=\"django.views.decorators.http.etag\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">etag()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/5.1/topics/http/decorators/#django.views.decorators.http.last_modified\" title=\"django.views.decorators.http.last_modified\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">last_modified()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/5.1/topics/http/decorators/#django.views.decorators.http.require_http_methods\" title=\"django.views.decorators.http.require_http_methods\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">require_http_methods()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/5.1/topics/http/decorators/#django.views.decorators.http.require_GET\" title=\"django.views.decorators.http.require_GET\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">require_GET()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/5.1/topics/http/decorators/#django.views.decorators.http.require_POST\" title=\"django.views.decorators.http.require_POST\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">require_POST()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/5.1/topics/http/decorators/#django.views.decorators.http.require_safe\" title=\"django.views.decorators.http.require_safe\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">require_safe()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/5.1/topics/http/decorators/#django.views.decorators.vary.vary_on_cookie\" title=\"django.views.decorators.vary.vary_on_cookie\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">vary_on_cookie()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/5.1/topics/http/decorators/#django.views.decorators.vary.vary_on_headers\" title=\"django.views.decorators.vary.vary_on_headers\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">vary_on_headers()</span></code></a></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">xframe_options_deny()</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">xframe_options_sameorigin()</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">xframe_options_exempt()</span></code></p></li>\n</ul>\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\">from</span><span class=\"w\"> </span><span class=\"nn\">django.views.decorators.cache</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">never_cache</span>\n\n\n<span class=\"nd\">@never_cache</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_sync_view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span> <span class=\"o\">...</span>\n\n\n<span class=\"nd\">@never_cache</span>\n<span class=\"k\">async</span> <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_async_view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span> <span class=\"o\">...</span>\n</code></pre></div>\n</section>\n<section id=\"queries-the-orm\">\n<h3>Requêtes et ORM<a class=\"heading-anchor\" href=\"#queries-the-orm\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>À part quelques exceptions, Django peut aussi lancer des requêtes d’ORM de manière asynchrone</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\">for</span> <span class=\"n\">author</span> <span class=\"ow\">in</span> <span class=\"n\">Author</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">name__startswith</span><span class=\"o\">=</span><span class=\"s2\">&quot;A&quot;</span><span class=\"p\">):</span>\n    <span class=\"n\">book</span> <span class=\"o\">=</span> <span class=\"k\">await</span> <span class=\"n\">author</span><span class=\"o\">.</span><span class=\"n\">books</span><span class=\"o\">.</span><span class=\"n\">afirst</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>Des notes détaillées peuvent être consultées dans <a class=\"reference internal\" href=\"/fr/5.1/topics/db/queries/#async-queries\"><span class=\"std std-ref\">Requêtes asynchrones</span></a>, mais en résumé :</p>\n<ul class=\"simple\">\n<li><p>Toutes les méthodes <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet</span></code> générant une requête SQL possèdent une variante asynchrone dotée du préfixe <code class=\"docutils literal notranslate\"><span class=\"pre\">a</span></code>.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">async</span> <span class=\"pre\">for</span></code> est pris en charge pour tous les QuerySets (y compris les résultats de <code class=\"docutils literal notranslate\"><span class=\"pre\">values()</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">values_list()</span></code>).</p></li>\n</ul>\n<p>Django prend également en charge certaines méthodes de modèles asynchrones qui utilisent la base de données</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\">make_book</span><span class=\"p\">(</span><span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n    <span class=\"n\">book</span> <span class=\"o\">=</span> <span class=\"n\">Book</span><span class=\"p\">(</span><span class=\"o\">...</span><span class=\"p\">)</span>\n    <span class=\"k\">await</span> <span class=\"n\">book</span><span class=\"o\">.</span><span class=\"n\">asave</span><span class=\"p\">(</span><span class=\"n\">using</span><span class=\"o\">=</span><span class=\"s2\">&quot;secondary&quot;</span><span class=\"p\">)</span>\n\n\n<span class=\"k\">async</span> <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">make_book_with_tags</span><span class=\"p\">(</span><span class=\"n\">tags</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n    <span class=\"n\">book</span> <span class=\"o\">=</span> <span class=\"k\">await</span> <span class=\"n\">Book</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">acreate</span><span class=\"p\">(</span><span class=\"o\">...</span><span class=\"p\">)</span>\n    <span class=\"k\">await</span> <span class=\"n\">book</span><span class=\"o\">.</span><span class=\"n\">tags</span><span class=\"o\">.</span><span class=\"n\">aset</span><span class=\"p\">(</span><span class=\"n\">tags</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Les transactions ne fonctionnent pas encore en mode asynchrone. Si vous écrivez un bout de code nécessitant un comportement transactionnel, nous vous recommandons de l’écrire sous forme d’une seule fonction synchrone et de l’appeler avec <a class=\"reference internal\" href=\"#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>.</p>\n<p>Les <a class=\"reference internal\" href=\"/fr/5.1/ref/databases/#persistent-database-connections\"><span class=\"std std-ref\">connexions persistantes à la base de données</span></a> définies par le réglage  <a class=\"reference internal\" href=\"/fr/5.1/ref/settings/#std-setting-CONN_MAX_AGE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CONN_MAX_AGE</span></code></a>, devraient aussi être désactivées en mode asynchrone. À la place, nous suggérons d’utiliser le système de pool de connexions de votre moteur de base de données, si disponible, ou recherchez un système de tierce partie si nécessaire.</p>\n</section>\n<section id=\"performance\">\n<span id=\"async-performance\"></span><h3>Performance<a class=\"heading-anchor\" href=\"#performance\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Lorsque vous fonctionnez dans un mode qui ne correspond pas à celui de la vue (par ex. une vue asynchrone avec WSGI ou une vue synchrone traditionnelle avec ASGI), Django doit émuler l’autre style d’appel pour permettre au code de s’exécuter. Cette bascule de contexte provoque une petite pénalité de performance d’environ une milliseconde.</p>\n<p>Ceci vaut aussi pour les intergiciels. Django essaie de minimiser le nombre de bascules de contexte entre code synchrone et asynchrone. Si vous fonctionnez avec un serveur ASGI mais que tous vos intergiciels et vues sont synchrones, la bascule ne se fait qu’une fois, avant d’entrer dans la pile des intergiciels.</p>\n<p>Cependant, si vous placez un intergiciel synchrone entre un serveur ASGI et une vue asynchrone, Django devra basculer en mode synchrone pour l’intergiciel puis revenir en mode asynchrone pour la vue. Il devra aussi laisser le fil d’exécution synchrone ouvert pour la propagation des exceptions d’intergiciel. Cela peut être d’abord à peine perceptible, mais cet handicap d’un fil d’exécution par requête peut potentiellement supprimer les avantages de la performance asynchrone.</p>\n<p>Nous suggérons de faire vos propres tests de performance pour observer les différences entre ASGI et WSGI avec votre code. Dans certains cas, les performances peuvent être meilleures avec ASGI même pour une base de code purement synchrone car le code de traitement des requêtes fonctionne toujours de manière asynchrone. Mais en général, l’activation du mode ASGI n’est profitable que si votre code contient du code asynchrone.</p>\n</section>\n<section id=\"handling-disconnects\">\n<span id=\"async-handling-disconnect\"></span><h3>Gestion des déconnexions<a class=\"heading-anchor\" href=\"#handling-disconnects\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<aside class=\"version-note version-added\" data-version=\"5.0\">\n<p class=\"version-note-title\">New in Django 5.0</p></aside>\n<p>Pour les requêtes de longue durée, un client peut se déconnecter avant que la vue renvoie une réponse. Dans ce cas, <code class=\"docutils literal notranslate\"><span class=\"pre\">asyncio.CancelledError</span></code> sera générée dans la vue. Vous pouvez intercepter cette erreur et la traiter si vous avez besoin d’effectuer un quelconque nettoyage :</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_view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"k\">try</span><span class=\"p\">:</span>\n        <span class=\"c1\"># Do some work</span>\n        <span class=\"o\">...</span>\n    <span class=\"k\">except</span> <span class=\"n\">asyncio</span><span class=\"o\">.</span><span class=\"n\">CancelledError</span><span class=\"p\">:</span>\n        <span class=\"c1\"># Handle disconnect</span>\n        <span class=\"k\">raise</span>\n</code></pre></div>\n<p>Vous pouvez aussi <a class=\"reference internal\" href=\"/fr/5.1/ref/request-response/#request-response-streaming-disconnect\"><span class=\"std std-ref\">traiter les déconnexions de client dans les réponses en flux</span></a>.</p>\n</section>\n</section>\n<section id=\"async-safety\">\n<span id=\"id1\"></span><h2>Isolation de code asynchrone<a class=\"heading-anchor\" href=\"#async-safety\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<dl class=\"std envvar\">\n<dt class=\"sig sig-object std\" id=\"envvar-DJANGO_ALLOW_ASYNC_UNSAFE\">\n<span class=\"sig-name descname\"><span class=\"pre\">DJANGO_ALLOW_ASYNC_UNSAFE</span></span><a class=\"heading-anchor\" href=\"#envvar-DJANGO_ALLOW_ASYNC_UNSAFE\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Certaines parties essentielles de Django ne sont pas capables d’opération de manière sûre dans un environnement asynchrone, car elles se basent sur un état global qui n’est pas compatible avec les coroutines. Ces parties de Django sont classées comme non sûres pour l’asynchrone (« async-unsafe ») et sont protégées contre l’exécution dans un environnement asynchrone. L’exemple principal est l’ORM (dialogue avec les bases de données), mais d’autres parties sont protégées de la même manière.</p>\n<p>Si vous essayez d’exécuter l’une de ces parties depuis un fil d’exécution où une <em>boucle événementielle s’exécute</em>, vous obtiendrez une erreur <a class=\"reference internal\" href=\"/fr/5.1/ref/exceptions/#django.core.exceptions.SynchronousOnlyOperation\" title=\"django.core.exceptions.SynchronousOnlyOperation\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">SynchronousOnlyOperation</span></code></a>. Notez que vous n’avez pas besoin d’être directement dans une fonction asynchrone pour déclencher cette erreur. Si vous avez appelé une fonction synchrone directement depuis une fonction asynchrone sans utiliser <a class=\"reference internal\" href=\"#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> ou un équivalent, cela peut alors aussi arriver, car votre code se trouve encore dans un fil d’exécution avec une boucle événementielle active, même s’il n’est pas déclaré comme code asynchrone.</p>\n<p>Si vous obtenez cette erreur, vous devriez corriger votre code pour qu’il n’appelle pas le code de manière fautive depuis un contexte asynchrone. Au lieu de cela, écrivez le code communiquant avec des fonctions non adaptées à l’asynchrone dans sa propre fonction synchrone et en l’appelant par <a class=\"reference internal\" href=\"#asgiref.sync.sync_to_async\" title=\"asgiref.sync.sync_to_async\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">asgiref.sync.sync_to_async()</span></code></a> (ou toute autre méthode d’exécution de code synchrone dans son propre fil d’exécution).</p>\n<p>Le contexte asynchrone peut vous être imposé par l’environnement dans lequel s’exécute le code Django. Par exemple, les carnets <a class=\"reference external\" href=\"https://jupyter.org/\">Jupyter</a> et les shells interactifs <a class=\"reference external\" href=\"https://ipython.org\">IPython</a> fournissent tous deux de manière transparente une boucle évènementielle active pour qu’il soit plus facile d’interagir avec des API asynchrones.</p>\n<p>Si vous utilisez un shell IPython, vous pouvez désactiver cette boucle évènementielle en exécutant :</p>\n<div class=\"code-block\" data-language=\"shell\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</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=\"Shell code\"><code>%autoawait<span class=\"w\"> </span>off\n</code></pre></div>\n<p>comme commande à l’invite IPython. Cela permet d’exécuter du code synchrone sans que des erreurs <a class=\"reference internal\" href=\"/fr/5.1/ref/exceptions/#django.core.exceptions.SynchronousOnlyOperation\" title=\"django.core.exceptions.SynchronousOnlyOperation\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">SynchronousOnlyOperation</span></code></a> se produisent ; cependant, vous ne serez pas non plus capable d’appeler des API asynchrones par <code class=\"docutils literal notranslate\"><span class=\"pre\">await</span></code>. Pour réactiver la boucle évènementielle, exécutez :</p>\n<div class=\"code-block\" data-language=\"shell\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</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=\"Shell code\"><code>%autoawait<span class=\"w\"> </span>on\n</code></pre></div>\n<p>Si vous vous trouvez dans un environnement autre que IPython (ou que vous ne pouvez pas désactiver <code class=\"docutils literal notranslate\"><span class=\"pre\">autoawait</span></code> dans IPython pour une raison quelconque), que vous êtes <em>certain</em> qu’il n’y a aucun risque que le code soit lancé de manière concurrente et que vous avez <em>absolument</em> besoin de lancer ce code synchrone à partir d’un contexte asynchrone, vous pouvez alors désactiver l’avertissement en définissant la variable d’environnement <span class=\"target\" id=\"index-2\"></span><a class=\"reference internal\" href=\"#envvar-DJANGO_ALLOW_ASYNC_UNSAFE\"><code class=\"xref std std-envvar docutils literal notranslate\"><span class=\"pre\">DJANGO_ALLOW_ASYNC_UNSAFE</span></code></a> à une valeur quelconque.</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Avertissement</p>\n<p>Si vous activez cette option et qu’un accès concurrent se produit sur des parties de Django non adaptées à l’asynchrone, vous pourriez expérimenter des pertes ou des corruptions de données. Soyez très prudent et n’utilisez pas cela dans des environnements de production.</p>\n</aside>\n<p>Si vous devez faire cela depuis du code Python, faites-le avec <code class=\"docutils literal notranslate\"><span class=\"pre\">os.environ</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\">import</span><span class=\"w\"> </span><span class=\"nn\">os</span>\n\n<span class=\"n\">os</span><span class=\"o\">.</span><span class=\"n\">environ</span><span class=\"p\">[</span><span class=\"s2\">&quot;DJANGO_ALLOW_ASYNC_UNSAFE&quot;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;true&quot;</span>\n</code></pre></div>\n</section>\n<section id=\"async-adapter-functions\">\n<h2>Fonctions d’adaptation asynchrone<a class=\"heading-anchor\" href=\"#async-adapter-functions\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Il est nécessaire d’adapter le style d’appel lors des appels de code synchrone depuis un contexte asynchrone ou vice versa. Il existe pour cela deux fonctions d’adaptation dans le module <code class=\"docutils literal notranslate\"><span class=\"pre\">asgiref.sync</span></code>: <a class=\"reference internal\" href=\"#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> et <a class=\"reference internal\" href=\"#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>. Elles sont utiles pour faire le passage entre les styles d’appel tout en préservant la compatibilité.</p>\n<p>Ces fonctions d’adaptation sont largement utilisées dans Django. Le paquet <a class=\"extlink-pypi reference external\" href=\"https://pypi.org/project/asgiref/\">asgiref</a> lui-même fait partie du projet Django et il est automatiquement installé comme dépendance lorsqu’on installe Django avec <code class=\"docutils literal notranslate\"><span class=\"pre\">pip</span></code>.</p>\n<section id=\"async-to-sync\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">async_to_sync()</span></code><a class=\"heading-anchor\" href=\"#async-to-sync\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"asgiref.sync.async_to_sync\">\n<span class=\"sig-name descname\"><span class=\"pre\">async_to_sync</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">async_function</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">force_new_loop</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">False</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#asgiref.sync.async_to_sync\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Accepte une fonction asynchrone et renvoie une fonction synchrone qui l’enveloppe. Peut être utilisée sous forme directe ou comme 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=\"w\"> </span><span class=\"nn\">asgiref.sync</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">async_to_sync</span>\n\n\n<span class=\"k\">async</span> <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_data</span><span class=\"p\">():</span> <span class=\"o\">...</span>\n\n\n<span class=\"n\">sync_get_data</span> <span class=\"o\">=</span> <span class=\"n\">async_to_sync</span><span class=\"p\">(</span><span class=\"n\">get_data</span><span class=\"p\">)</span>\n\n\n<span class=\"nd\">@async_to_sync</span>\n<span class=\"k\">async</span> <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_other_data</span><span class=\"p\">():</span> <span class=\"o\">...</span>\n</code></pre></div>\n<p>La fonction asynchrone est exécutée dans la boucle événementielle du fil d’exécution actuel, le cas échéant. S’il n’y a pas de boucle événementielle, une nouvelle boucle est générée spécifiquement pour cette invocation asynchrone unique et arrêtée dès que la fonction est terminée. Quelle que soit la situation, la fonction asynchrone s’exécutera dans un fil d’exécution différent de celui du code appelant.</p>\n<p>Les valeurs « threadlocals » et « contextvars » sont préservées de part et d’autres des exécutions.</p>\n<p><a class=\"reference internal\" href=\"#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> est fondamentalement une version plus puissante de la fonction <a class=\"reference external\" href=\"https://docs.python.org/3/library/asyncio-runner.html#asyncio.run\" title=\"(disponible dans Python v3.14)\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">asyncio.run()</span></code></a> de la bibliothèque Python standard. En plus de s’assurer du fonctionnement de « threadlocals », elle active aussi le mode <code class=\"docutils literal notranslate\"><span class=\"pre\">thread_sensitive</span></code> de <a class=\"reference internal\" href=\"#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> lorsque cette dernière est utilisée en dessous d’elle.</p>\n</section>\n<section id=\"sync-to-async\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">sync_to_async()</span></code><a class=\"heading-anchor\" href=\"#sync-to-async\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"asgiref.sync.sync_to_async\">\n<span class=\"sig-name descname\"><span class=\"pre\">sync_to_async</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">sync_function</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">thread_sensitive</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">True</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#asgiref.sync.sync_to_async\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Accepte une fonction synchrone et renvoie une fonction asynchrone qui l’enveloppe. Peut être utilisée sous forme directe ou comme 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=\"w\"> </span><span class=\"nn\">asgiref.sync</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">sync_to_async</span>\n\n<span class=\"n\">async_function</span> <span class=\"o\">=</span> <span class=\"n\">sync_to_async</span><span class=\"p\">(</span><span class=\"n\">sync_function</span><span class=\"p\">,</span> <span class=\"n\">thread_sensitive</span><span class=\"o\">=</span><span class=\"kc\">False</span><span class=\"p\">)</span>\n<span class=\"n\">async_function</span> <span class=\"o\">=</span> <span class=\"n\">sync_to_async</span><span class=\"p\">(</span><span class=\"n\">sensitive_sync_function</span><span class=\"p\">,</span> <span class=\"n\">thread_sensitive</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n\n\n<span class=\"nd\">@sync_to_async</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">sync_function</span><span class=\"p\">():</span> <span class=\"o\">...</span>\n</code></pre></div>\n<p>Les valeurs « threadlocals » et « contextvars » sont préservées de part et d’autres des exécutions.</p>\n<p>Les fonctions synchrones ont tendances à être écrites en partant du principe qu’elles s’exécutent toutes dans le fil d’exécution principal, ce qui fait que <a class=\"reference internal\" href=\"#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> dispose de deux modes d’exécution :</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">thread_sensitive=True</span></code> (valeur par défaut) : la fonction synchrone sera exécutée dans le même fil d’exécution que toutes les autres fonctions <code class=\"docutils literal notranslate\"><span class=\"pre\">thread_sensitive</span></code>. Ce fil sera le fil principal si celui-ci est synchrone et que vous utilisez la fonction enveloppeuse <a class=\"reference internal\" href=\"#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>.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">thread_sensitive=False</span></code>: la fonction synchrone sera exécutée dans un tout nouveau fil d’exécution qui sera ensuite détruit lorsque l’invocation sera terminée.</p></li>\n</ul>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Avertissement</p>\n<p>La version 3.3.0 de <code class=\"docutils literal notranslate\"><span class=\"pre\">asgiref</span></code> a modifié la valeur par défaut du paramètre <code class=\"docutils literal notranslate\"><span class=\"pre\">thread_sensitive</span></code> à <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>. Il s’agit d’une valeur par défaut plus sûre et la bonne valeur dans de nombreuses situations d’interaction avec Django, mais prenez soin d’évaluer les utilisations de <code class=\"docutils literal notranslate\"><span class=\"pre\">sync_to_async()</span></code> si vous mettez à jour <code class=\"docutils literal notranslate\"><span class=\"pre\">asgiref</span></code> à partir d’une version plus ancienne.</p>\n</aside>\n<p>Le mode « thread-sensitive » est très spécial et fait beaucoup d’efforts pour exécuter toutes les fonctions dans le même fil d’exécution. Notez toutefois qu’il <em>compte sur l’utilisation de</em> <a class=\"reference internal\" href=\"#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> <em>au-dessus de lui dans la pile d’appels</em> pour lancer les choses correctement dans le fil d’exécution principal. Si vous utilisez <code class=\"docutils literal notranslate\"><span class=\"pre\">asyncio.run()</span></code> ou une méthode semblable, il se limite à exécuter les fonctions dépendantes du fil d’exécution dans un seul fil partagé, mais il ne s’agira pas du fil d’exécution principal.</p>\n<p>La raison de sa présence dans Django est que de nombreuses bibliothèques, particulièrement les adaptateurs de base de données, exigent que leur accès se fasse dans le même fil d’exécution dans lequel elles ont été créées. De même, une grande quantité de code existant dans Django présuppose qu’il s’exécute entièrement dans le même fil d’exécution, par ex. un intergiciel ajoutant des éléments à une requête pour utilisation ultérieure dans les vues.</p>\n<p>Plutôt que d’introduire des problèmes potentiels de compatibilité avec ce code, nous avons choisi d’ajouter ce mode afin que tout code synchrone existant dans Django soit exécuté dans le même fil d’exécution et reste donc pleinement compatible avec le mode asynchrone. Notez que le code synchrone sera toujours exécuté dans un fil d’exécution <em>différent</em> du code asynchrone appelant, ce qui implique que vous devez éviter de passer des pointeurs bruts de base de données ou d’autres références sensibles au fil d’exécution.</p>\n<p>En pratique, cette restriction signifie que vous ne devriez pas transmettre des fonctionnalités de l’objet de base de données <code class=\"docutils literal notranslate\"><span class=\"pre\">connection</span></code> lors de l’appel à <code class=\"docutils literal notranslate\"><span class=\"pre\">sync_to_async()</span></code>. Si vous le faites, cela déclenchera les contrôles de sécurité des fils d’exécution :</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</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=\"Python console code\"><code><span class=\"go\"># DJANGO_SETTINGS_MODULE=settings.py python -m asyncio</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">import</span><span class=\"w\"> </span><span class=\"nn\">asyncio</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">asgiref.sync</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">sync_to_async</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">connection</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># In an async context so you cannot use the database directly:</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">connection</span><span class=\"o\">.</span><span class=\"n\">cursor</span><span class=\"p\">()</span>\n<span class=\"go\">django.core.exceptions.SynchronousOnlyOperation: You cannot call this from</span>\n<span class=\"go\">an async context - use a thread or sync_to_async.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># Nor can you pass resolved connection attributes across threads:</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"k\">await</span> <span class=\"n\">sync_to_async</span><span class=\"p\">(</span><span class=\"n\">connection</span><span class=\"o\">.</span><span class=\"n\">cursor</span><span class=\"p\">)()</span>\n<span class=\"go\">django.db.utils.DatabaseError: DatabaseWrapper objects created in a thread</span>\n<span class=\"go\">can only be used in that same thread. The object with alias &#39;default&#39; was</span>\n<span class=\"go\">created in thread id 4371465600 and this is thread id 6131478528.</span>\n</code></pre></div>\n<p>Au lieu de cela, vous devriez encapsuler tous les accès à la base de données dans une fonction utilitaire pouvant être appelée par <code class=\"docutils literal notranslate\"><span class=\"pre\">sync_to_async()</span></code> sans vous baser sur l’objet de connexion dans le code appelant.</p>\n</section>\n</section>","rootId":"asynchronous-support","toc":[{"title":"Vues asynchrones","anchor":"async-views","children":[{"title":"Décorateurs","anchor":"decorators","children":[]},{"title":"Requêtes et ORM","anchor":"queries-the-orm","children":[]},{"title":"Performance","anchor":"performance","children":[]},{"title":"Gestion des déconnexions","anchor":"handling-disconnects","children":[]}]},{"title":"Isolation de code asynchrone","anchor":"async-safety","children":[]},{"title":"Fonctions d’adaptation asynchrone","anchor":"async-adapter-functions","children":[{"title":"async_to_sync()","anchor":"async-to-sync","children":[]},{"title":"sync_to_async()","anchor":"sync-to-async","children":[]}]}],"breadcrumbs":[{"docname":"topics/index","title":"Utilisation de Django","url":"/fr/5.1/topics/"}],"prev":{"docname":"topics/external-packages","title":"Paquets externes","url":"/fr/5.1/topics/external-packages/"},"next":{"docname":"howto/index","title":"Guides pratiques","url":"/fr/5.1/howto/"},"formats":{"html":"/fr/5.1/topics/async/","markdown":"/fr/5.1/topics/async.md","json":"/fr/5.1/topics/async.json"},"source":"https://github.com/django/django/blob/stable/5.1.x/docs/topics/async.txt","official":"https://docs.djangoproject.com/fr/5.1/topics/async/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0"],"inLocales":["en","zh-hans","fr","ja","id","it","pt-br","ko","es","el","pl"]}