{"title":"Soporte asíncrono","version":"5.1","locale":"es","docname":"topics/async","url":"/es/5.1/topics/async/","canonical":"https://djangodocs.dev/es/5.1/topics/async/","summary":"Django tiene soporte para escribir vistas asíncronas («async»), junto con una pila de solicitudes completamente habilitada para el asincronismo si se está…","html":"<h1>Soporte asíncrono<a class=\"heading-anchor\" href=\"#asynchronous-support\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>Django tiene soporte para escribir vistas asíncronas («async»), junto con una pila de solicitudes completamente habilitada para el asincronismo si se está ejecutando bajo <a class=\"reference internal\" href=\"/es/5.1/howto/deployment/asgi/\"><span class=\"doc\">ASGI</span></a>. Las vistas asíncronas seguirán funcionando con WSGI, pero con problemas de rendimiento y sin la capacidad de tener solicitudes prolongadas eficientes.</p>\n<p>Todavía estamos trabajando en el soporte asíncrono para el ORM y otras partes de Django. Puede esperar ver esto en futuras versiones. Por ahora, puede usar el adaptador <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> para interactuar con las partes de sincronización de Django. También hay una amplia gama de bibliotecas asíncronas y nativas de Python con las que puede integrarse.</p>\n<section id=\"async-views\">\n<h2>Vistas asincrónicas<a class=\"heading-anchor\" href=\"#async-views\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Cualquier vista puede declararse asincrónica haciendo que la parte invocable devuelva una corrutina; comúnmente, esto se hace usando <code class=\"docutils literal notranslate\"><span class=\"pre\">async</span> <span class=\"pre\">def</span></code>. Para una vista basada en funciones, esto significa declarar la vista completa usando <code class=\"docutils literal notranslate\"><span class=\"pre\">async</span> <span class=\"pre\">def</span></code>. Para una vista basada en clases, esto significa declarar los manejadors de métodos HTTP como <code class=\"docutils literal notranslate\"><span class=\"pre\">get()</span></code> and <code class=\"docutils literal notranslate\"><span class=\"pre\">post()</span></code> como <code class=\"docutils literal notranslate\"><span class=\"pre\">async</span> <span class=\"pre\">def</span></code> (no su <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\">Nota</p>\n<p>Django uses <code class=\"docutils literal notranslate\"><span class=\"pre\">asgiref.sync.iscoroutinefunction</span></code> to test if your view is\nasynchronous or not. If you implement your own method of returning a\ncoroutine, ensure you use <code class=\"docutils literal notranslate\"><span class=\"pre\">asgiref.sync.markcoroutinefunction</span></code> so this\nfunction returns <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>.</p>\n</aside>\n<p>En un servidor WSGI, las vistas asíncronas se ejecutarán en su propio bucle de eventos. Esto significa que puede usar funciones asíncronas, como peticiones HTTP asíncronas concurrentes, sin ningún problema, pero no obtendrá los beneficios de una pila asíncrona.</p>\n<p>Los principales beneficios son la capacidad de dar servicio a cientos de conexiones sin utilizar hilos de Python. Esto le permite usar transmisión lenta, sondeos largos (long-polling) y otros tipos de respuesta interesantes.</p>\n<p>Si desea usarlos, deberá desplegar Django usando <a class=\"reference internal\" href=\"/es/5.1/howto/deployment/asgi/\"><span class=\"doc\">ASGI</span></a> en su lugar.</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Advertencia</p>\n<p>Solo obtendrá los beneficios de una pila de peticiones totalmente asincrónica si no tiene <em>ningún middleware sincrónico</em> cargado en su sitio. Si hay una pieza de middleware sincrónico, entonces Django debe usar un hilo por solicitud para emular de forma segura un entorno sincrónico para él.</p>\n<p>Middleware can be built to support <a class=\"reference internal\" href=\"/es/5.1/topics/http/middleware/#async-middleware\"><span class=\"std std-ref\">both sync and async</span></a> contexts. Some of Django’s middleware is built like\nthis, but not all. To see what middleware Django has to adapt for, you can\nturn on debug logging for the <code class=\"docutils literal notranslate\"><span class=\"pre\">django.request</span></code> logger and look for log\nmessages about <em>«Asynchronous handler adapted for middleware …»</em>.</p>\n</aside>\n<p>Tanto en el modo ASGI como en el WSGI, aún puede utilizar de forma segura el soporte asincrónico para ejecutar código de forma simultánea en lugar de en serie. Esto es especialmente útil cuando se trata de APIs externas o almacenes de datos.</p>\n<p>If you want to call a part of Django that is still synchronous, you will need\nto wrap it in a <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> call. For example:</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>If you accidentally try to call a part of Django that is synchronous-only\nfrom an async view, you will trigger Django’s\n<a class=\"reference internal\" href=\"#async-safety\"><span class=\"std std-ref\">asynchronous safety protection</span></a> to protect your data from\ncorruption.</p>\n<section id=\"decorators\">\n<h3>Decoradores<a class=\"heading-anchor\" href=\"#decorators\"><span class=\"visually-hidden\">Link to this heading</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>Los siguientes decoradores pueden ser usados tanto con funciones de vistas síncronas, como asíncronas:</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"/es/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=\"/es/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=\"/es/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=\"/es/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=\"/es/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=\"/es/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=\"/es/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=\"/es/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=\"/es/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=\"/es/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=\"/es/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=\"/es/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=\"/es/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=\"/es/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=\"/es/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=\"/es/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=\"/es/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=\"/es/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=\"/es/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>Por ejemplo:</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>Consultas y ORM<a class=\"heading-anchor\" href=\"#queries-the-orm\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Con algunas excepciones, Django también puede ejecutar consultas ORM de manera asíncrona:</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>Notas detalladas se pueden encontrar en <a class=\"reference internal\" href=\"/es/5.1/topics/db/queries/#async-queries\"><span class=\"std std-ref\">Asynchronous queries</span></a>, pero en resumen:</p>\n<ul class=\"simple\">\n<li><p>Todas los métodos de <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet</span></code> que provocan una consulta SQL tienen una variante asíncrona con el prefijo <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> is supported on all QuerySets (including the output of\n<code class=\"docutils literal notranslate\"><span class=\"pre\">values()</span></code> and <code class=\"docutils literal notranslate\"><span class=\"pre\">values_list()</span></code>.)</p></li>\n</ul>\n<p>Django also supports some asynchronous model methods that use the database:</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>Transactions do not yet work in async mode. If you have a piece of code that\nneeds transactions behavior, we recommend you write that piece as a single\nsynchronous function and call it using <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><a class=\"reference internal\" href=\"/es/5.1/ref/databases/#persistent-database-connections\"><span class=\"std std-ref\">Persistent database connections</span></a>, set\nvia the <a class=\"reference internal\" href=\"/es/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> setting, should also be disabled in async mode.\nInstead, use your database backend’s built-in connection pooling if available,\nor investigate a third-party connection pooling option if required.</p>\n</section>\n<section id=\"performance\">\n<span id=\"async-performance\"></span><h3>Rendimiento<a class=\"heading-anchor\" href=\"#performance\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>When running in a mode that does not match the view (e.g. an async view under\nWSGI, or a traditional sync view under ASGI), Django must emulate the other\ncall style to allow your code to run. This context-switch causes a small\nperformance penalty of around a millisecond.</p>\n<p>This is also true of middleware. Django will attempt to minimize the number of\ncontext-switches between sync and async. If you have an ASGI server, but all\nyour middleware and views are synchronous, it will switch just once, before it\nenters the middleware stack.</p>\n<p>However, if you put synchronous middleware between an ASGI server and an\nasynchronous view, it will have to switch into sync mode for the middleware and\nthen back to async mode for the view. Django will also hold the sync thread\nopen for middleware exception propagation. This may not be noticeable at first,\nbut adding this penalty of one thread per request can remove any async\nperformance advantage.</p>\n<p>You should do your own performance testing to see what effect ASGI versus WSGI\nhas on your code. In some cases, there may be a performance increase even for\na purely synchronous codebase under ASGI because the request-handling code is\nstill all running asynchronously. In general you will only want to enable ASGI\nmode if you have asynchronous code in your project.</p>\n</section>\n<section id=\"handling-disconnects\">\n<span id=\"async-handling-disconnect\"></span><h3>Handling disconnects<a class=\"heading-anchor\" href=\"#handling-disconnects\"><span class=\"visually-hidden\">Link to this heading</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>For long-lived requests, a client may disconnect before the view returns a\nresponse. In this case, an <code class=\"docutils literal notranslate\"><span class=\"pre\">asyncio.CancelledError</span></code> will be raised in the\nview. You can catch this error and handle it if you need to perform any\ncleanup:</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>You can also <a class=\"reference internal\" href=\"/es/5.1/ref/request-response/#request-response-streaming-disconnect\"><span class=\"std std-ref\">handle client disconnects in streaming responses</span></a>.</p>\n</section>\n</section>\n<section id=\"async-safety\">\n<span id=\"id1\"></span><h2>Seguridad asíncrona<a class=\"heading-anchor\" href=\"#async-safety\"><span class=\"visually-hidden\">Link to this heading</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\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Certain key parts of Django are not able to operate safely in an async\nenvironment, as they have global state that is not coroutine-aware. These parts\nof Django are classified as «async-unsafe», and are protected from execution in\nan async environment. The ORM is the main example, but there are other parts\nthat are also protected in this way.</p>\n<p>If you try to run any of these parts from a thread where there is a <em>running\nevent loop</em>, you will get a\n<a class=\"reference internal\" href=\"/es/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> error. Note that you\ndon’t have to be inside an async function directly to have this error occur. If\nyou have called a sync function directly from an async function,\nwithout using <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> or similar, then it can also occur. This is\nbecause your code is still running in a thread with an active event loop, even\nthough it may not be declared as async code.</p>\n<p>If you encounter this error, you should fix your code to not call the offending\ncode from an async context. Instead, write your code that talks to async-unsafe\nfunctions in its own, sync function, and call that using\n<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> (or any other way of running sync code in\nits own thread).</p>\n<p>The async context can be imposed upon you by the environment in which you are\nrunning your Django code. For example, <a class=\"reference external\" href=\"https://jupyter.org/\">Jupyter</a> notebooks and <a class=\"reference external\" href=\"https://ipython.org\">IPython</a>\ninteractive shells both transparently provide an active event loop so that it is\neasier to interact with asynchronous APIs.</p>\n<p>If you’re using an IPython shell, you can disable this event loop by running:</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>as a command at the IPython prompt. This will allow you to run synchronous code\nwithout generating <a class=\"reference internal\" href=\"/es/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>\nerrors; however, you also won’t be able to <code class=\"docutils literal notranslate\"><span class=\"pre\">await</span></code> asynchronous APIs. To turn\nthe event loop back on, run:</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>If you’re in an environment other than IPython (or you can’t turn off\n<code class=\"docutils literal notranslate\"><span class=\"pre\">autoawait</span></code> in IPython for some reason), you are <em>certain</em> there is no chance\nof your code being run concurrently, and you <em>absolutely</em> need to run your sync\ncode from an async context, then you can disable the warning by setting the\n<span class=\"target\" id=\"index-0\"></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> environment variable to any value.</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Advertencia</p>\n<p>If you enable this option and there is concurrent access to the\nasync-unsafe parts of Django, you may suffer data loss or corruption. Be\nvery careful and do not use this in production environments.</p>\n</aside>\n<p>If you need to do this from within Python, do that with <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>Funciones adaptadoras asíncronas<a class=\"heading-anchor\" href=\"#async-adapter-functions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>It is necessary to adapt the calling style when calling sync code from an async\ncontext, or vice-versa. For this there are two adapter functions, from the\n<code class=\"docutils literal notranslate\"><span class=\"pre\">asgiref.sync</span></code> module: <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> and <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>. They\nare used to transition between the calling styles while preserving\ncompatibility.</p>\n<p>These adapter functions are widely used in Django. The <a class=\"extlink-pypi reference external\" href=\"https://pypi.org/project/asgiref/\">asgiref</a> package\nitself is part of the Django project, and it is automatically installed as a\ndependency when you install Django with <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\">Link to this heading</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\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Takes an async function and returns a sync function that wraps it. Can be used\nas either a direct wrapper or a decorator:</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>The async function is run in the event loop for the current thread, if one is\npresent. If there is no current event loop, a new event loop is spun up\nspecifically for the single async invocation and shut down again once it\ncompletes. In either situation, the async function will execute on a different\nthread to the calling code.</p>\n<p>Threadlocals and contextvars values are preserved across the boundary in both\ndirections.</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> is essentially a more powerful version of the\n<a class=\"reference external\" href=\"https://docs.python.org/3/library/asyncio-runner.html#asyncio.run\" title=\"(en Python versión 3.14)\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">asyncio.run()</span></code></a> function in Python’s standard library. As well\nas ensuring threadlocals work, it also enables the <code class=\"docutils literal notranslate\"><span class=\"pre\">thread_sensitive</span></code> mode of\n<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> when that wrapper is used below it.</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\">Link to this heading</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\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Takes a sync function and returns an async function that wraps it. Can be used\nas either a direct wrapper or a decorator:</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>Threadlocals and contextvars values are preserved across the boundary in both\ndirections.</p>\n<p>Sync functions tend to be written assuming they all run in the main\nthread, so <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> has two threading modes:</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">thread_sensitive=True</span></code> (the default): the sync function will run in the\nsame thread as all other <code class=\"docutils literal notranslate\"><span class=\"pre\">thread_sensitive</span></code> functions. This will be the\nmain thread, if the main thread is synchronous and you are using the\n<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> wrapper.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">thread_sensitive=False</span></code>: the sync function will run in a brand new thread\nwhich is then closed once the invocation completes.</p></li>\n</ul>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Advertencia</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">asgiref</span></code> version 3.3.0 changed the default value of the\n<code class=\"docutils literal notranslate\"><span class=\"pre\">thread_sensitive</span></code> parameter to <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>. This is a safer default, and in\nmany cases interacting with Django the correct value, but be sure to\nevaluate uses of <code class=\"docutils literal notranslate\"><span class=\"pre\">sync_to_async()</span></code> if updating <code class=\"docutils literal notranslate\"><span class=\"pre\">asgiref</span></code> from a prior\nversion.</p>\n</aside>\n<p>Thread-sensitive mode is quite special, and does a lot of work to run all\nfunctions in the same thread. Note, though, that it <em>relies on usage of</em>\n<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>above it in the stack</em> to correctly run things on the\nmain thread. If you use <code class=\"docutils literal notranslate\"><span class=\"pre\">asyncio.run()</span></code> or similar, it will fall back to\nrunning thread-sensitive functions in a single, shared thread, but this will\nnot be the main thread.</p>\n<p>The reason this is needed in Django is that many libraries, specifically\ndatabase adapters, require that they are accessed in the same thread that they\nwere created in. Also a lot of existing Django code assumes it all runs in the\nsame thread, e.g. middleware adding things to a request for later use in views.</p>\n<p>Rather than introduce potential compatibility issues with this code, we instead\nopted to add this mode so that all existing Django sync code runs in the same\nthread and thus is fully compatible with async mode. Note that sync code will\nalways be in a <em>different</em> thread to any async code that is calling it, so you\nshould avoid passing raw database handles or other thread-sensitive references\naround.</p>\n<p>In practice this restriction means that you should not pass features of the\ndatabase <code class=\"docutils literal notranslate\"><span class=\"pre\">connection</span></code> object when calling <code class=\"docutils literal notranslate\"><span class=\"pre\">sync_to_async()</span></code>. Doing so will\ntrigger the thread safety checks:</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>Rather, you should encapsulate all database access within a helper function\nthat can be called with <code class=\"docutils literal notranslate\"><span class=\"pre\">sync_to_async()</span></code> without relying on the connection\nobject in the calling code.</p>\n</section>\n</section>","rootId":"asynchronous-support","toc":[{"title":"Vistas asincrónicas","anchor":"async-views","children":[{"title":"Decoradores","anchor":"decorators","children":[]},{"title":"Consultas y ORM","anchor":"queries-the-orm","children":[]},{"title":"Rendimiento","anchor":"performance","children":[]},{"title":"Handling disconnects","anchor":"handling-disconnects","children":[]}]},{"title":"Seguridad asíncrona","anchor":"async-safety","children":[]},{"title":"Funciones adaptadoras asíncronas","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":"Using Django","url":"/es/5.1/topics/"}],"prev":{"docname":"topics/external-packages","title":"External packages","url":"/es/5.1/topics/external-packages/"},"next":{"docname":"howto/index","title":"How-to guides","url":"/es/5.1/howto/"},"formats":{"html":"/es/5.1/topics/async/","markdown":"/es/5.1/topics/async.md","json":"/es/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/es/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"]}