{"title":"非同期サポート","version":"6.0","locale":"ja","docname":"topics/async","url":"/ja/6.0/topics/async/","canonical":"https://djangodocs.dev/ja/6.0/topics/async/","summary":"Django has support for writing asynchronous (\"async\") views, along with an entirely async-enabled request stack if you are running under ASGI.","html":"<h1>非同期サポート<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 has support for writing asynchronous (&quot;async&quot;) views, along with an\nentirely async-enabled request stack if you are running under <a class=\"reference internal\" href=\"/ja/6.0/howto/deployment/asgi/\"><span class=\"doc\">ASGI</span></a>. Async views will still work under WSGI, but\nwith a small per-request adaptation cost (see <a class=\"reference internal\" href=\"#async-performance\"><span class=\"std std-ref\">パフォーマンス</span></a>), and\nwithout the ability to have efficient long-running requests.</p>\n<p>Many parts of Django provide asynchronous APIs, including <a class=\"reference internal\" href=\"/ja/6.0/topics/db/queries/#async-queries\"><span class=\"std std-ref\">the ORM</span></a>, the cache framework, authentication, sessions, and signals.\nFor other code, the <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\">sync_to_async()</code></a> adapter is a low-cost bridge (see\n<a class=\"reference internal\" href=\"#async-performance\"><span class=\"std std-ref\">パフォーマンス</span></a>). A wide range of async-native Python libraries can\nalso be integrated.</p>\n<section id=\"async-views\">\n<h2>非同期ビュー<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>どのようなビューでも、呼び出し可能オブジェクトでコルーチンを返すようにすれば、非同期として宣言できます。その際には、一般的に <code class=\"docutils literal notranslate\">async def</code> を使います。関数ベースのビューの場合、<code class=\"docutils literal notranslate\">async def</code> を用いてビュー全体を宣言します。クラスベースのビューの場合、<code class=\"docutils literal notranslate\">get()</code> と <code class=\"docutils literal notranslate\">post()</code> などのメソッドを <code class=\"docutils literal notranslate\">async def</code> で宣言します (<code class=\"docutils literal notranslate\">__init__()</code> でも <code class=\"docutils literal notranslate\">as_view()</code> でもないことに注意)。</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">注釈</p>\n<p>Django は、あなたのビューが非同期かどうか確かめるために <code class=\"docutils literal notranslate\">asgiref.sync.iscoroutinefunction</code> を使います。もし、コルーチンを返すあなた独自のメソッドを実装する場合は、確実に <code class=\"docutils literal notranslate\">asgiref.sync.markcoroutinefunction</code> を用いて <code class=\"docutils literal notranslate\">asgiref.sync.iscoroutinefunction</code> が <code class=\"docutils literal notranslate\">True</code> を返すようにして下さい。</p>\n</aside>\n<p>WSGI サーバーでは、非同期ビューは1回限りのイベントループで実行されます。つまり、非同期 HTTP リクエストなどの非同期機能を問題なく使用できるものの、非同期スタックのメリットは得られないことになります。</p>\n<p>非同期スタックの主な利点とは、数百もの接続を Python のスレッドを使わずに処理できることです。これにより、低速ストリーミング、ロングポーリング、その他の便利なレスポンスタイプが使えます。</p>\n<p>もしこれらを利用したい場合は、代わりに <a class=\"reference internal\" href=\"/ja/6.0/howto/deployment/asgi/\"><span class=\"doc\">ASGI</span></a> を使って Django をデプロイする必要があります。</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">注釈</p>\n<p>A fully asynchronous request stack requires async middleware end-to-end.\nWhere a piece of synchronous middleware sits between an ASGI server and an\nasync view, Django adapts it by running it in its own thread; see\n<a class=\"reference internal\" href=\"#async-performance\"><span class=\"std std-ref\">パフォーマンス</span></a> for the cost trade-off.</p>\n<p>Django's bundled middleware supports both <a class=\"reference internal\" href=\"/ja/6.0/topics/http/middleware/#async-middleware\"><span class=\"std std-ref\">sync and async</span></a>. Third-party middleware may not. To see which\nmiddleware Django adapts, turn on debug logging for the <code class=\"docutils literal notranslate\">django.request</code>\nlogger and look for log messages about <em>&quot;Asynchronous handler adapted for\nmiddleware ...&quot;</em>.</p>\n</aside>\n<p>ASGI モードと WSGI モードの両方で、コードを逐次的ではなく並行して実行するために、非同期サポートを安全に使用できます。これは、外部 API やデータストアを扱う際に特に便利です。</p>\n<p>まだ同期的な Django の機能を呼び出したい場合、次のように <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\">sync_to_async()</code></a> でラップする必要があります。</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">asgiref.sync</span> <span class=\"kn\">import</span> sync_to_async\n\nresults <span class=\"o\">=</span> <span class=\"k\">await</span> sync_to_async<span class=\"p\">(</span>sync_function<span class=\"p\">,</span> thread_sensitive<span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)(</span>pk<span class=\"o\">=</span><span class=\"mi\">123</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>非同期ビューから、同期的な Django の機能を誤って呼び出そうとすると、Django の <a class=\"reference internal\" href=\"#async-safety\"><span class=\"std std-ref\">非同期セーフティプロテクション</span></a> が発動して、データが破損しないように保護されます。</p>\n<section id=\"decorators\">\n<h3>デコレータ<a class=\"heading-anchor\" href=\"#decorators\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>以下のデコレータは、同期ビュー関数でも非同期ビュー関数でも使用できます。</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"/ja/6.0/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\">cache_control()</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/6.0/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\">never_cache()</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/6.0/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\">no_append_slash()</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/6.0/ref/csp/#django.views.decorators.csp.csp_override\" title=\"django.views.decorators.csp.csp_override\"><code class=\"xref py py-func docutils literal notranslate\">csp_override()</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/6.0/ref/csp/#django.views.decorators.csp.csp_report_only_override\" title=\"django.views.decorators.csp.csp_report_only_override\"><code class=\"xref py py-func docutils literal notranslate\">csp_report_only_override()</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/6.0/ref/csrf/#django.views.decorators.csrf.csrf_exempt\" title=\"django.views.decorators.csrf.csrf_exempt\"><code class=\"xref py py-func docutils literal notranslate\">csrf_exempt()</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/6.0/ref/csrf/#django.views.decorators.csrf.csrf_protect\" title=\"django.views.decorators.csrf.csrf_protect\"><code class=\"xref py py-func docutils literal notranslate\">csrf_protect()</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/6.0/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\">ensure_csrf_cookie()</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/6.0/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\">requires_csrf_token()</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/6.0/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\">sensitive_variables()</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/6.0/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\">sensitive_post_parameters()</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/6.0/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\">gzip_page()</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/6.0/topics/http/decorators/#django.views.decorators.http.condition\" title=\"django.views.decorators.http.condition\"><code class=\"xref py py-func docutils literal notranslate\">condition()</code></a></p></li>\n<li><p><code class=\"docutils literal notranslate\">conditional_page()</code></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/6.0/topics/http/decorators/#django.views.decorators.http.etag\" title=\"django.views.decorators.http.etag\"><code class=\"xref py py-func docutils literal notranslate\">etag()</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/6.0/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\">last_modified()</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/6.0/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\">require_http_methods()</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/6.0/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\">require_GET()</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/6.0/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\">require_POST()</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/6.0/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\">require_safe()</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/6.0/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\">vary_on_cookie()</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/6.0/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\">vary_on_headers()</code></a></p></li>\n<li><p><code class=\"docutils literal notranslate\">xframe_options_deny()</code></p></li>\n<li><p><code class=\"docutils literal notranslate\">xframe_options_sameorigin()</code></p></li>\n<li><p><code class=\"docutils literal notranslate\">xframe_options_exempt()</code></p></li>\n</ul>\n<p>例:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.views.decorators.cache</span> <span class=\"kn\">import</span> never_cache\n\n\n<span class=\"nd\">@never_cache</span>\n<span class=\"k\">def</span> <span class=\"nf\">my_sync_view</span><span class=\"p\">(</span>request<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=\"nf\">my_async_view</span><span class=\"p\">(</span>request<span class=\"p\">):</span> <span class=\"o\">...</span>\n</code></pre></div>\n</section>\n<section id=\"queries-the-orm\">\n<h3>クエリーと 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>With some exceptions, Django can run ORM queries asynchronously:</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> author <span class=\"ow\">in</span> Author<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>name__startswith<span class=\"o\">=</span><span class=\"s2\">&quot;A&quot;</span><span class=\"p\">):</span>\n    book <span class=\"o\">=</span> <span class=\"k\">await</span> author<span class=\"o\">.</span>books<span class=\"o\">.</span>afirst<span class=\"p\">()</span>\n</code></pre></div>\n<p>詳細については <a class=\"reference internal\" href=\"/ja/6.0/topics/db/queries/#async-queries\"><span class=\"std std-ref\">非同期クエリ</span></a> で参照できますが、簡単にまとめると次のようになります。</p>\n<ul class=\"simple\">\n<li><p>SQL クエリを発行するすべての <code class=\"docutils literal notranslate\">QuerySet</code> メソッドには、<code class=\"docutils literal notranslate\">a</code> という接頭辞が付いた非同期版があります。</p></li>\n<li><p><code class=\"docutils literal notranslate\">async for</code> は (<code class=\"docutils literal notranslate\">values()</code> と <code class=\"docutils literal notranslate\">values_list()</code> を含む) すべての QuerySet でサポートされている</p></li>\n</ul>\n<p>Asynchronous model methods that use the database are also supported:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">async</span> <span class=\"k\">def</span> <span class=\"nf\">make_book</span><span class=\"p\">(</span><span class=\"o\">*</span>args<span class=\"p\">,</span> <span class=\"o\">**</span>kwargs<span class=\"p\">):</span>\n    book <span class=\"o\">=</span> Book<span class=\"p\">(</span><span class=\"o\">...</span><span class=\"p\">)</span>\n    <span class=\"k\">await</span> book<span class=\"o\">.</span>asave<span class=\"p\">(</span>using<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=\"nf\">make_book_with_tags</span><span class=\"p\">(</span>tags<span class=\"p\">,</span> <span class=\"o\">*</span>args<span class=\"p\">,</span> <span class=\"o\">**</span>kwargs<span class=\"p\">):</span>\n    book <span class=\"o\">=</span> <span class=\"k\">await</span> Book<span class=\"o\">.</span>objects<span class=\"o\">.</span>acreate<span class=\"p\">(</span><span class=\"o\">...</span><span class=\"p\">)</span>\n    <span class=\"k\">await</span> book<span class=\"o\">.</span>tags<span class=\"o\">.</span>aset<span class=\"p\">(</span>tags<span class=\"p\">)</span>\n</code></pre></div>\n<p>トランザクションは非同期モードではまだ機能しません。もしトランザクションの動作が必要なコードがある場合は、そのコードを1つの同期的な関数として書いて、<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\">sync_to_async()</code></a> を使用して呼び出すことをおすすめします。</p>\n<p><a class=\"reference internal\" href=\"/ja/6.0/ref/databases/#persistent-database-connections\"><span class=\"std std-ref\">Persistent database connections</span></a>, set\nvia the <a class=\"reference internal\" href=\"/ja/6.0/ref/settings/#std-setting-CONN_MAX_AGE\"><code class=\"xref std std-setting docutils literal notranslate\">CONN_MAX_AGE</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. As in\nsynchronous Django, concurrent requests in a single process share that pool, so\nsize it to the target in-flight query concurrency.</p>\n</section>\n<section id=\"performance\">\n<span id=\"async-performance\"></span><h3>パフォーマンス<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. The per-call cost of this adaptation is\nsmall: tens of microseconds in the in-request ASGI path, where the running\nevent loop is reused, and a few hundred microseconds in the cold-start path\nused by management commands, background tasks, and scripts. Against typical\nrequest times measured in milliseconds, this is rarely visible in itself, but\ncan become so under GIL contention as the number of active threads grows.</p>\n<p>If you find yourself wrapping individual rows or operations in a tight loop,\nrestructure your code so the loop runs inside a single <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\">sync_to_async()</code></a>\n(or <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\">async_to_sync()</code></a>) crossing. The per-call cost of the context switch is\nthen spread across the whole loop and effectively disappears.</p>\n<p>The same per-call adaptation cost applies to middleware. Django will attempt to\nminimize the number of context-switches between sync and async. If you have an\nASGI server, but all your middleware and views are synchronous, it will switch\njust once, before it enters 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. For request/response views that hit\nthe ORM and return, this is not usually a meaningful penalty. It matters most\nwhen you are using ASGI for high in-process concurrency over non-ORM I/O (for\nexample upstream HTTP fan-out, server-sent events, or other long-lived\nrequests), where the extra thread per request caps that concurrency.</p>\n<p>自分のコード上での ASGI と WSGI の違いの影響を知るためには、自分自身でパフォーマンステストを行うべきです。場合によっては、純粋に同期的なコードベースを ASGI 上で実行した場合でも、性能が向上することがあります。これは、それでもリクエストハンドリングのコードはすべて非同期に実行されるためです。一般的には、ASGI モードを有効にする必要があるのは、プロジェクトに非同期のコードがあるときだけです。</p>\n</section>\n<section id=\"handling-disconnects\">\n<span id=\"async-handling-disconnect\"></span><h3>切断をハンドリングする<a class=\"heading-anchor\" href=\"#handling-disconnects\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>長時間のリクエストの場合、ビューが応答を返す前にクライアントが切断することがあります。この場合、asyncio.CancelledErrorがビューで発生します。このエラーをキャッチし、クリーンアップが必要な場合にハンドリングできます:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">async</span> <span class=\"k\">def</span> <span class=\"nf\">my_view</span><span class=\"p\">(</span>request<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> asyncio<span class=\"o\">.</span>CancelledError<span class=\"p\">:</span>\n        <span class=\"c1\"># Handle disconnect</span>\n        <span class=\"k\">raise</span>\n</code></pre></div>\n<p>また、<a class=\"reference internal\" href=\"/ja/6.0/ref/request-response/#request-response-streaming-disconnect\"><span class=\"std std-ref\">ストリーミングレスポンスでクライアントの切断をハンドリングする</span></a> こともできます。</p>\n</section>\n</section>\n<section id=\"async-safety\">\n<span id=\"id1\"></span><h2>非同期安全性<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\">DJANGO_ALLOW_ASYNC_UNSAFE</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 &quot;async-unsafe&quot;, and are protected from execution in\nan async environment. The synchronous API of the ORM is the main example, but\nthere are other parts that are also protected in this way.</p>\n<p><em>実行中のイベントループ</em> があるスレッドからこれらのパーツを実行しようとすると、 <a class=\"reference internal\" href=\"/ja/6.0/ref/exceptions/#django.core.exceptions.SynchronousOnlyOperation\" title=\"django.core.exceptions.SynchronousOnlyOperation\"><code class=\"xref py py-exc docutils literal notranslate\">SynchronousOnlyOperation</code></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\">sync_to_async()</code></a> などを使わずに、非同期関数から直接同期関数を呼び出した場合にも発生します。これは、コードが同期コードとして宣言されていなくても、アクティブなイベントループを持つスレッドで実行されているためです。</p>\n<p>このエラーが発生した場合は、問題のコードを非同期コンテキストから呼び出さないように修正する必要があります。代わりに、独自の同期関数それ自体の中で async-unsafe と通信するコードを書き、  <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\">asgiref.sync.sync_to_async()</code></a> (または、自スレッド内で同期コードを実行するための他の方法) を使って呼び出します。</p>\n<p>非同期コンテキストは、Django コードを実行している環境によって与えられる場合もあります。たとえば、<a class=\"reference external\" href=\"https://jupyter.org/\">Jupyter</a> notebooks や <a class=\"reference external\" href=\"https://ipython.org\">IPython</a> 対話シェルはともにアクティブなイベントループを透過的に提供してくれるため、非同期 API との対話がより簡単になります。</p>\n<p>もし IPython shell を使用している場合は、次のコマンドでこのイベントループを無効化できます。</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 off\n</code></pre></div>\n<p>これは IPython のプロンプトのコマンドです。これにより同期的なコードを <a class=\"reference internal\" href=\"/ja/6.0/ref/exceptions/#django.core.exceptions.SynchronousOnlyOperation\" title=\"django.core.exceptions.SynchronousOnlyOperation\"><code class=\"xref py py-exc docutils literal notranslate\">SynchronousOnlyOperation</code></a> エラーを起こさずに実行できるようになりますが、同時に、非同期 API を <code class=\"docutils literal notranslate\">await</code> することもできなくなります。イベントループを戻すには、次のコマンドを実行します。</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 on\n</code></pre></div>\n<p>IPython 以外の環境にいる場合 (または、何らかの理由で IPython で <code class=\"docutils literal notranslate\">autoawait</code> がオフにできない場合)、コードが並行して実行される可能性は <em>確実に</em> ないため、同期コードは <em>絶対に</em> 非同期コンテキストから実行する必要があります。このとき、警告は <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\">DJANGO_ALLOW_ASYNC_UNSAFE</code></a> 環境変数を任意の値に設定することで無効化できます。</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">警告</p>\n<p>このオプションを有効にした上で、Djangoの  async-unsafe パーツへ同時アクセスがあると、データが失われたり壊れたりする可能性があります。十分な注意を払い、本番環境では使用しないでください。</p>\n</aside>\n<p>もし、これをPython内部から行いたい場合は、<code class=\"docutils literal notranslate\">os.environ</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=\"nn\">os</span>\n\nos<span class=\"o\">.</span>environ<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>非同期アダプター関数<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>同期コードを非同期コンテキストから呼び出したり、その逆をするためには、呼び出しスタイルを調整する必要があります。このために <code class=\"docutils literal notranslate\">asgiref.sync</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\">async_to_sync()</code></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\">sync_to_async()</code></a> という2つのアダプター関数があります。これらは互換性を維持したまま呼び出しスタイル間を移行するために使われます。</p>\n<p>これらのアダプター関数は Django で幅広く利用されています。<a class=\"extlink-pypi reference external\" href=\"https://pypi.org/project/asgiref/\">asgiref</a> パッケージ自体が Django プロジェクトの一部になっており、Django を <code class=\"docutils literal notranslate\">pip</code> でインストールしたときに自動的に依存関係としてインストールされます。</p>\n<section id=\"async-to-sync\">\n<h3><code class=\"docutils literal notranslate\">async_to_sync()</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\">async_to_sync</span><span class=\"sig-paren\">(</span><em class=\"sig-param\">async_function</em>, <em class=\"sig-param\">force_new_loop<span class=\"o\">=</span><span class=\"default_value\">False</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>非同期関数を取り、それをラッピングした同期関数を返します。直接ラッパーとしてもデコレーターとしても使用できます。</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">asgiref.sync</span> <span class=\"kn\">import</span> async_to_sync\n\n\n<span class=\"k\">async</span> <span class=\"k\">def</span> <span class=\"nf\">get_data</span><span class=\"p\">():</span> <span class=\"o\">...</span>\n\n\nsync_get_data <span class=\"o\">=</span> async_to_sync<span class=\"p\">(</span>get_data<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=\"nf\">get_other_data</span><span class=\"p\">():</span> <span class=\"o\">...</span>\n</code></pre></div>\n<p>非同期関数は、もし存在すれば、現在のスレッドのイベントループの中で実行されます。現在のイベントループが存在しない場合、1つの非同期呼び出しのために専用の新しいイベントループが生成され、完了したら再び破棄されます。どちらの状況でも、非同期関数はコードが呼び出されたスレッドとは異なるスレッドで実行されます。</p>\n<p>threadlocal とコンテキスト変数の値は双方向に境界を越えて保持されます。</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\">async_to_sync()</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=\"(in Python v3.14)\"><code class=\"xref py py-func docutils literal notranslate\">asyncio.run()</code></a> function in Python's standard library. As well as ensuring\nthreadlocals work, it also enables the <code class=\"docutils literal notranslate\">thread_sensitive</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\">sync_to_async()</code></a> when that wrapper is used below it. In the cold path\n(no running event loop) it pays the cost of starting a fresh event loop, like\n<a class=\"reference external\" href=\"https://docs.python.org/3/library/asyncio-runner.html#asyncio.run\" title=\"(in Python v3.14)\"><code class=\"xref py py-func docutils literal notranslate\">asyncio.run()</code></a>; when an event loop is already running (the in-request ASGI\ncase), the running loop is reused and the cost drops accordingly.</p>\n</section>\n<section id=\"sync-to-async\">\n<h3><code class=\"docutils literal notranslate\">sync_to_async()</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\">sync_to_async</span><span class=\"sig-paren\">(</span><em class=\"sig-param\">sync_function</em>, <em class=\"sig-param\">thread_sensitive<span class=\"o\">=</span><span class=\"default_value\">True</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>同期関数を取り、それをラッピングした非同期関数を返します。直接ラッパーとしてもデコレーターとしても使用できます。</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">asgiref.sync</span> <span class=\"kn\">import</span> sync_to_async\n\nasync_function <span class=\"o\">=</span> sync_to_async<span class=\"p\">(</span>sync_function<span class=\"p\">,</span> thread_sensitive<span class=\"o\">=</span><span class=\"kc\">False</span><span class=\"p\">)</span>\nasync_function <span class=\"o\">=</span> sync_to_async<span class=\"p\">(</span>sensitive_sync_function<span class=\"p\">,</span> thread_sensitive<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=\"nf\">sync_function</span><span class=\"p\">():</span> <span class=\"o\">...</span>\n</code></pre></div>\n<p>threadlocal とコンテキスト変数の値は双方向に境界を越えて保持されます。</p>\n<p>同期関数はすべてメインスレッド内で実行されることを想定して書かれる傾向があるため、<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\">sync_to_async()</code></a> には2種類の threading モードがあります。</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\">thread_sensitive=True</code> (デフォルト): 同期関数は他のすべての <code class=\"docutils literal notranslate\">thread_sensitive</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\">async_to_sync()</code></a> ラッパーを使用している場合、このスレッドはメインスレッドになるでしょう。</p></li>\n<li><p><code class=\"docutils literal notranslate\">thread_sensitive=False</code>: 同期関数は、まったく新しいスレッドで実行されます。そのスレッドは、その後呼び出しが完了すると閉じられます。</p></li>\n</ul>\n<p>thread-sensitive モードは極めて特別なモードで、すべての関数が同一スレッドで実行されるようにするためにたくさんの仕事を行います。ただし、メインスレッドで正しく動作するように、<em>スタック内での</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\">async_to_sync()</code></a> <em>の使用に依存している</em> ことに注意してください。もし <code class=\"docutils literal notranslate\">asyncio.run()</code> や類似のメソッドを使用した場合、thread-sensitive な関数は単一の共有スレッドでの実行にフォールバックしますが、これはメインスレッドではありません。</p>\n<p>Django でこれが必要な理由は、多くのライブラリ、特にデータベースアダプターが、自分が作られたのと同一スレッド内でのアクセスを必要とするためです。また、既存の多くの Django コードも、すべてが同一スレッドで実行されることを想定しています。たとえば、ビュー内で後で使用するためにリクエストに何かを追加するミドルウェアです。</p>\n<p>このコードによって潜在的な互換性の問題を引き起こす代わりに、私たちはこのモードを追加する選択をしました。これにより、既存のすべての Django の同期コードが同一スレッドで実行されるようになり、したがって、非同期モードと完全に互換になります。同期コードは、それを呼び出すすべての非同期コードとは常に <em>異なる</em> スレッド内にあるため、生のデータベースハンドルや、その他 thread-sensitive な参照を渡すことは避ける必要があることに注意してください。</p>\n<p>Within a single request, multiple <code class=\"docutils literal notranslate\">thread_sensitive</code> calls serialize on that\nrequest's worker thread, but each request gets its own per-context worker, so\nconcurrent requests do <em>not</em> serialize against each other. This mirrors\nDjango's connection-per-thread model, and the same constraint applies in other\nasync database libraries, where concurrent queries on a single connection\nserialize on a lock. To support more concurrent requests, increase the\nconnection pool size accordingly rather than disabling <code class=\"docutils literal notranslate\">thread_sensitive</code>.</p>\n<p>実用的には、この制限は、<code class=\"docutils literal notranslate\">sync_to_async()</code> を呼び出すときにデータベースの <code class=\"docutils literal notranslate\">connection</code> オブジェクトの機能を渡してはならないことを意味します。もしそうした場合、スレッド安全性のチェックがトリガーされます:</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=\"nn\">asyncio</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span> <span class=\"nn\">asgiref.sync</span> <span class=\"kn\">import</span> sync_to_async\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span> <span class=\"nn\">django.db</span> <span class=\"kn\">import</span> connection\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>connection<span class=\"o\">.</span>cursor<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> sync_to_async<span class=\"p\">(</span>connection<span class=\"o\">.</span>cursor<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>代わりに、呼び出しコード内の connection オブジェクトに依存せずに、<code class=\"docutils literal notranslate\">sync_to_async()</code> で呼び出すことができるヘルパー関数内にすべてのデータベースアクセスをカプセル化する必要があります。</p>\n</section>\n</section>","rootId":"asynchronous-support","toc":[{"title":"非同期ビュー","anchor":"async-views","children":[{"title":"デコレータ","anchor":"decorators","children":[]},{"title":"クエリーと ORM","anchor":"queries-the-orm","children":[]},{"title":"パフォーマンス","anchor":"performance","children":[]},{"title":"切断をハンドリングする","anchor":"handling-disconnects","children":[]}]},{"title":"非同期安全性","anchor":"async-safety","children":[]},{"title":"非同期アダプター関数","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":"Django を使う","url":"/ja/6.0/topics/"}],"prev":{"docname":"topics/external-packages","title":"外部パッケージ","url":"/ja/6.0/topics/external-packages/"},"next":{"docname":"topics/tasks","title":"Django's Tasks framework","url":"/ja/6.0/topics/tasks/"},"formats":{"html":"/ja/6.0/topics/async/","markdown":"/ja/6.0/topics/async.md","json":"/ja/6.0/topics/async.json"},"source":"https://github.com/django/django/blob/stable/6.0.x/docs/topics/async.txt","official":"https://docs.djangoproject.com/ja/6.0/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","sv","zh-hans","ga","fr","ja","id","it","pt-br","ko","es","el","pl"]}