{"title":"非同期サポート","version":"5.0","locale":"ja","docname":"topics/async","url":"/ja/5.0/topics/async/","canonical":"https://djangodocs.dev/ja/5.0/topics/async/","summary":"Djangoは、 ASGI の環境下であれば、完璧な非同期リクエストスタックに対応した非同期 (\"async\") ビューをサポートしています。WSGI の環境下でも非同期ビューは動作しますが、パフォーマンス上不利であるうえ、長期的なリクエストを効率的に処理できません。 開発チームは ORM…","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は、<a class=\"reference internal\" href=\"/ja/5.0/howto/deployment/asgi/\"><span class=\"doc\">ASGI</span></a> の環境下であれば、完璧な非同期リクエストスタックに対応した非同期 (&quot;async&quot;) ビューをサポートしています。WSGI の環境下でも非同期ビューは動作しますが、パフォーマンス上不利であるうえ、長期的なリクエストを効率的に処理できません。</p>\n<p>開発チームは ORM や他の機能でも非同期処理が対応できるよう取り組んでいます。この機能は将来リリース予定ですが、現時点では、同期処理と非同期処理のやり取りに、<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> アダプターが使えます。さらに同期処理と非同期処理を統合するために、非同期な Python ライブラリがすべて使えます。</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\"><span class=\"pre\">async</span> <span class=\"pre\">def</span></code> を使います。関数ベースのビューの場合、<code class=\"docutils literal notranslate\"><span class=\"pre\">async</span> <span class=\"pre\">def</span></code> を用いてビュー全体を宣言します。クラスベースのビューの場合、<code class=\"docutils literal notranslate\"><span class=\"pre\">get()</span></code> と <code class=\"docutils literal notranslate\"><span class=\"pre\">post()</span></code> などのメソッドを <code class=\"docutils literal notranslate\"><span class=\"pre\">async</span> <span class=\"pre\">def</span></code> で宣言します (<code class=\"docutils literal notranslate\"><span class=\"pre\">__init__()</span></code> でも <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\">注釈</p>\n<p>Django は、あなたのビューが非同期かどうか確かめるために <code class=\"docutils literal notranslate\"><span class=\"pre\">asgiref.sync.iscoroutinefunction</span></code> を使います。もし、コルーチンを返すあなた独自のメソッドを実装する場合は、確実に <code class=\"docutils literal notranslate\"><span class=\"pre\">asgiref.sync.markcoroutinefunction</span></code> を用いて <code class=\"docutils literal notranslate\"><span class=\"pre\">asgiref.sync.iscoroutinefunction</span></code> が <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> を返すようにして下さい。</p>\n</aside>\n<p>WSGI サーバーでは、非同期ビューは1回限りのイベントループで実行されます。つまり、非同期 HTTP リクエストなどの非同期機能を問題なく使用できるものの、非同期スタックのメリットは得られないことになります。</p>\n<p>非同期スタックの主な利点とは、数百もの接続を Python のスレッドを使わずに処理できることです。これにより、低速ストリーミング、ロングポーリング、その他の便利なレスポンスタイプが使えます。</p>\n<p>もしこれらを利用したい場合は、代わりに <a class=\"reference internal\" href=\"/ja/5.0/howto/deployment/asgi/\"><span class=\"doc\">ASGI</span></a> を使って Django をデプロイする必要があります。</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">警告</p>\n<p>同期ミドルウェアを使っていない場合にのみ、完全非同期のリクエストスタックの効果があります。もし、同期ミドルウェアがあれば、同期環境を安全にエミュレートするために、Django はリクエストごとにスレッドを使ってしまいます。</p>\n<p>ミドルウェアは、<a class=\"reference internal\" href=\"/ja/5.0/topics/http/middleware/#async-middleware\"><span class=\"std std-ref\">同期と非同期の両方の</span></a> コンテキストをサポートするように構築できます。 Djangoミドルウェアの一部はこのように構築されていますが、すべてではありません。ミドルウェアが適応する必要があるものを確認するには、<code class=\"docutils literal notranslate\"><span class=\"pre\">django.request</span></code> ロガーのデバッグロギングを有効にして、<em>&quot;Asynchronous handler adapted for middleware ...&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\"><span class=\"pre\">sync_to_async()</span></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=\"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>非同期ビューから、同期的な 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<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>以下のデコレータは、同期ビュー関数でも非同期ビュー関数でも使用できます。</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">cache_control()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">never_cache()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">no_append_slash()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">csrf_exempt()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">csrf_protect()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">ensure_csrf_cookie()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">requires_csrf_token()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">sensitive_variables()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">sensitive_post_parameters()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">gzip_page()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/5.0/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=\"/ja/5.0/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=\"/ja/5.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\"><span class=\"pre\">last_modified()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">require_http_methods()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">require_GET()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">require_POST()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">require_safe()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">vary_on_cookie()</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/5.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\"><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>例:</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>クエリーと 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>一部の例外を除いて、Django は ORM クエリーを非同期に実行することもできます。</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>詳細については <a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">QuerySet</span></code> メソッドには、<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> は (<code class=\"docutils literal notranslate\"><span class=\"pre\">values()</span></code> と <code class=\"docutils literal notranslate\"><span class=\"pre\">values_list()</span></code> を含む) すべての QuerySet でサポートされている</p></li>\n</ul>\n<p>Django は、次のような非同期モデルのデータベースを使用するメソッドもいくつかサポートします。</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>トランザクションは非同期モードではまだ機能しません。もしトランザクションの動作が必要なコードがある場合は、そのコードを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\"><span class=\"pre\">sync_to_async()</span></code></a> を使用して呼び出すことをおすすめします。</p>\n<aside class=\"version-note version-changed\" data-version=\"4.2\">\n<p class=\"version-note-title\">Changed in Django 4.2</p><p>非同期モデルと関連するマネージャーインターフェイスが追加されました。</p>\n</aside>\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>ビューと異なるモードで実行 (たとえば、非同期のビューを WSGI で実行、従来の同期ビューを ASGI で実行) した場合、Django はコードを実行するために、もう一方の呼び出しスタイルをエミュレートする必要があります。コンテキストスイッチにより、1 ms 程度の小さな性能上のペナルティが与えられてしまいます。</p>\n<p>これはミドルウェアでも同様です。Django は同期・非同期の間のコンテキストスイッチの数を最小化するように試みます。もし ASGI サーバーがあっても、すべてのミドルウェアとビューが同期的だった場合、コンテキストスイッチは、サーバーがミドルウェアスタックに入る前の1回だけです。</p>\n<p>しかし、同期ミドルウェアをASGIサーバーと非同期ビューの間においた場合、サーバーはミドルウェアのために同期モードに切り替え、ビューのために非同期モードにまた戻さなければならなくなります。Django はミドルウェアの例外の伝搬のために同期スレッドも保持し続けます。これは初めは気づかないほどの違いかもしれませんが、1リクエストごとに1スレッドのペナルティが与えられると、非同期の性能上の利点がすべて打ち消されてしまう可能性があります。</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<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>長時間のリクエストの場合、ビューが応答を返す前にクライアントが切断することがあります。この場合、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=\"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>また、<a class=\"reference internal\" href=\"/ja/5.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\"><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>Django の特定の主要なパーツは、コルーチンが感知できないグローバルステートを持つため、非同期の環境では安全に操作できません。これらの Django のパーツは、&quot;async-unsafe&quot; として分類されており、非同期な環境での実行から保護されています。ORM は主な例ですが、この他にもこのように保護されているパーツがあります。</p>\n<p><em>実行中のイベントループ</em> があるスレッドからこれらのパーツを実行しようとすると、 <a class=\"reference internal\" href=\"/ja/5.0/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> エラーが発生します。このエラーは、非同期関数の内部でなくても発生することに注意してください。 <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>このエラーが発生した場合は、問題のコードを非同期コンテキストから呼び出さないように修正する必要があります。代わりに、独自の同期関数それ自体の中で 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\"><span class=\"pre\">asgiref.sync.sync_to_async()</span></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<span class=\"w\"> </span>off\n</code></pre></div>\n<p>これは IPython のプロンプトのコマンドです。これにより同期的なコードを <a class=\"reference internal\" href=\"/ja/5.0/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> エラーを起こさずに実行できるようになりますが、同時に、非同期 API を <code class=\"docutils literal notranslate\"><span class=\"pre\">await</span></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<span class=\"w\"> </span>on\n</code></pre></div>\n<p>IPython 以外の環境にいる場合 (または、何らかの理由で IPython で <code class=\"docutils literal notranslate\"><span class=\"pre\">autoawait</span></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\"><span class=\"pre\">DJANGO_ALLOW_ASYNC_UNSAFE</span></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\"><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>非同期アダプター関数<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>同期コードを非同期コンテキストから呼び出したり、その逆をするためには、呼び出しスタイルを調整する必要があります。このために``asgiref.sync`` モジュールの <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> と <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> という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\"><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>非同期関数を取り、それをラッピングした同期関数を返します。直接ラッパーとしてもデコレーターとしても使用できます。</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>非同期関数は、もし存在すれば、現在のスレッドのイベントループの中で実行されます。現在のイベントループが存在しない場合、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\"><span class=\"pre\">async_to_sync()</span></code></a> は、Python 標準ライブラリの <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\"><span class=\"pre\">asyncio.run()</span></code></a> 関数の強力なバージョンです。threadlocal が確実に機能するようにするだけでなく、それより下で <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> のラッパーが使用されるときに、<code class=\"docutils literal notranslate\"><span class=\"pre\">thread_sensitive</span></code> モードも有効にします。</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>同期関数を取り、それをラッピングした非同期関数を返します。直接ラッパーとしてもデコレーターとしても使用できます。</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>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\"><span class=\"pre\">sync_to_async()</span></code></a> には2種類の threading モードがあります。</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">thread_sensitive=True</span></code> (デフォルト): 同期関数は他のすべての <code class=\"docutils literal notranslate\"><span class=\"pre\">thread_sensitive</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> ラッパーを使用している場合、このスレッドはメインスレッドになるでしょう。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">thread_sensitive=False</span></code>: 同期関数は、まったく新しいスレッドで実行されます。そのスレッドは、その後呼び出しが完了すると閉じられます。</p></li>\n</ul>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">警告</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">asgiref</span></code> バージョン 3.3.0 は <code class=\"docutils literal notranslate\"><span class=\"pre\">thread_sensitive</span></code> のデフォルト値を <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> に変更しました。これは安全側のデフォルトなので、多くの場合、正しい値で Django とインタラクションしますが、以前のバージョンから <code class=\"docutils literal notranslate\"><span class=\"pre\">asgiref</span></code> をアップデートする場合は、必ず <code class=\"docutils literal notranslate\"><span class=\"pre\">sync_to_async()</span></code> の使用を評価してください。</p>\n</aside>\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\"><span class=\"pre\">async_to_sync()</span></code></a> <em>の使用に依存している</em> ことに注意してください。もし <code class=\"docutils literal notranslate\"><span class=\"pre\">asyncio.run()</span></code> や類似のメソッドを使用した場合、thread-sensitive な関数は単一の共有スレッドでの実行にフォールバックしますが、これはメインスレッドではありません。</p>\n<p>Django でこれが必要な理由は、多くのライブラリ、特にデータベースアダプターが、自分が作られたのと同一スレッド内でのアクセスを必要とするためです。また、既存の多くの Django コードも、すべてが同一スレッドで実行されることを想定しています。たとえば、ビュー内で後で使用するためにリクエストに何かを追加するミドルウェアです。</p>\n<p>このコードによって潜在的な互換性の問題を引き起こす代わりに、私たちはこのモードを追加する選択をしました。これにより、既存のすべての Django の同期コードが同一スレッドで実行されるようになり、したがって、非同期モードと完全に互換になります。同期コードは、それを呼び出すすべての非同期コードとは常に <em>異なる</em> スレッド内にあるため、生のデータベースハンドルや、その他 thread-sensitive な参照を渡すことは避ける必要があることに注意してください。</p>\n<p>実用的には、この制限は、<code class=\"docutils literal notranslate\"><span class=\"pre\">sync_to_async()</span></code> を呼び出すときにデータベースの <code class=\"docutils literal notranslate\"><span class=\"pre\">connection</span></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=\"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>代わりに、呼び出しコード内の connection オブジェクトに依存せずに、<code class=\"docutils literal notranslate\"><span class=\"pre\">sync_to_async()</span></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/5.0/topics/"}],"prev":{"docname":"topics/external-packages","title":"外部パッケージ","url":"/ja/5.0/topics/external-packages/"},"next":{"docname":"howto/index","title":"「How-to」ガイド","url":"/ja/5.0/howto/"},"formats":{"html":"/ja/5.0/topics/async/","markdown":"/ja/5.0/topics/async.md","json":"/ja/5.0/topics/async.json"},"source":"https://github.com/django/django/blob/stable/5.0.x/docs/topics/async.txt","official":"https://docs.djangoproject.com/ja/5.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","zh-hans","fr","ja","id","it","pt-br","ko","es","el","pl"]}