{"title":"条件付きビュー","version":"3.2","locale":"ja","docname":"topics/conditional-view-processing","url":"/ja/3.2/topics/conditional-view-processing/","canonical":"https://djangodocs.dev/ja/3.2/topics/conditional-view-processing/","summary":"HTTPクライアントは、すでに受信したリソースについてサーバーに伝えるため、いくつかのHTTPヘッダーを送信します。","html":"<h1>条件付きビュー<a class=\"heading-anchor\" href=\"#conditional-view-processing\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>HTTPクライアントは、すでに受信したリソースについてサーバーに伝えるため、いくつかのHTTPヘッダーを送信します。これらは一般的に <code class=\"docutils literal notranslate\">GET</code> メソッドを利用してウェブページを取得する際に、すでにクライアントが取得しているデータを送信しなくてよいようにするために用いられます。しかし、これらのヘッダーは <code class=\"docutils literal notranslate\">POST</code> ・ <code class=\"docutils literal notranslate\">PUT</code> ・ <code class=\"docutils literal notranslate\">DELETE</code> などの全てのHTTPメソッドで利用することができます。</p>\n<p>For each page (response) that Django sends back from a view, it might provide\ntwo HTTP headers: the <code class=\"docutils literal notranslate\">ETag</code> header and the <code class=\"docutils literal notranslate\">Last-Modified</code> header. These\nheaders are optional on HTTP responses. They can be set by your view function,\nor you can rely on the <a class=\"reference internal\" href=\"/ja/3.2/ref/middleware/#django.middleware.http.ConditionalGetMiddleware\" title=\"django.middleware.http.ConditionalGetMiddleware\"><code class=\"xref py py-class docutils literal notranslate\">ConditionalGetMiddleware</code></a>\nmiddleware to set the <code class=\"docutils literal notranslate\">ETag</code> header.</p>\n<p>When the client next requests the same resource, it might send along a header\nsuch as either <span class=\"target\" id=\"index-0\"></span><a class=\"rfc reference external\" href=\"https://datatracker.ietf.org/doc/html/rfc7232.html#section-3.3\"><strong>If-modified-since</strong></a> or\n<span class=\"target\" id=\"index-1\"></span><a class=\"rfc reference external\" href=\"https://datatracker.ietf.org/doc/html/rfc7232.html#section-3.4\"><strong>If-unmodified-since</strong></a>, containing the date of the last\nmodification time it was sent, or either <span class=\"target\" id=\"index-2\"></span><a class=\"rfc reference external\" href=\"https://datatracker.ietf.org/doc/html/rfc7232.html#section-3.1\"><strong>If-match</strong></a> or\n<span class=\"target\" id=\"index-3\"></span><a class=\"rfc reference external\" href=\"https://datatracker.ietf.org/doc/html/rfc7232.html#section-3.2\"><strong>If-none-match</strong></a>, containing the last <code class=\"docutils literal notranslate\">ETag</code> it was\nsent. If the current version of the page matches the <code class=\"docutils literal notranslate\">ETag</code> sent by the\nclient, or if the resource has not been modified, a 304 status code can be sent\nback, instead of a full response, telling the client that nothing has changed.\nDepending on the header, if the page has been modified or does not match the\n<code class=\"docutils literal notranslate\">ETag</code> sent by the client, a 412 status code (Precondition Failed) may be\nreturned.</p>\n<p>When you need more fine-grained control you may use per-view conditional\nprocessing functions.</p>\n<section id=\"the-condition-decorator\">\n<span id=\"conditional-decorators\"></span><h2><code class=\"docutils literal notranslate\">condition</code> デコレータ<a class=\"heading-anchor\" href=\"#the-condition-decorator\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Sometimes (in fact, quite often) you can create functions to rapidly compute\nthe <span class=\"target\" id=\"index-4\"></span><a class=\"rfc reference external\" href=\"https://datatracker.ietf.org/doc/html/rfc7232.html#section-2.3\"><strong>ETag</strong></a> value or the last-modified time for a\nresource, <strong>without</strong> needing to do all the computations needed to construct\nthe full view. Django can then use these functions to provide an\n&quot;early bailout&quot; option for the view processing. Telling the client that the\ncontent has not been modified since the last request, perhaps.</p>\n<p>These two functions are passed as parameters to the\n<code class=\"docutils literal notranslate\">django.views.decorators.http.condition</code> decorator. This decorator uses\nthe two functions (you only need to supply one, if you can't compute both\nquantities easily and quickly) to work out if the headers in the HTTP request\nmatch those on the resource. If they don't match, a new copy of the resource\nmust be computed and your normal view is called.</p>\n<p><code class=\"docutils literal notranslate\">condition</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>condition<span class=\"p\">(</span>etag_func<span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">,</span> last_modified_func<span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>The two functions, to compute the ETag and the last modified time, will be\npassed the incoming <code class=\"docutils literal notranslate\">request</code> object and the same parameters, in the same\norder, as the view function they are helping to wrap. The function passed\n<code class=\"docutils literal notranslate\">last_modified_func</code> should return a standard datetime value specifying the\nlast time the resource was modified, or <code class=\"docutils literal notranslate\">None</code> if the resource doesn't\nexist. The function passed to the <code class=\"docutils literal notranslate\">etag</code> decorator should return a string\nrepresenting the <span class=\"target\" id=\"index-5\"></span><a class=\"rfc reference external\" href=\"https://datatracker.ietf.org/doc/html/rfc7232.html#section-2.3\"><strong>ETag</strong></a> for the resource, or <code class=\"docutils literal notranslate\">None</code>\nif it doesn't exist.</p>\n<p>The decorator sets the <code class=\"docutils literal notranslate\">ETag</code> and <code class=\"docutils literal notranslate\">Last-Modified</code> headers on the response\nif they are not already set by the view and if the request's method is safe\n(<code class=\"docutils literal notranslate\">GET</code> or <code class=\"docutils literal notranslate\">HEAD</code>).</p>\n<p>Using this feature usefully is probably best explained with an example.\nSuppose you have this pair of models, representing a small blog system:</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\">datetime</span>\n<span class=\"kn\">from</span> <span class=\"nn\">django.db</span> <span class=\"kn\">import</span> models\n\n<span class=\"k\">class</span> <span class=\"nc\">Blog</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n\n<span class=\"k\">class</span> <span class=\"nc\">Entry</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    blog <span class=\"o\">=</span> models<span class=\"o\">.</span>ForeignKey<span class=\"p\">(</span>Blog<span class=\"p\">,</span> on_delete<span class=\"o\">=</span>models<span class=\"o\">.</span>CASCADE<span class=\"p\">)</span>\n    published <span class=\"o\">=</span> models<span class=\"o\">.</span>DateTimeField<span class=\"p\">(</span>default<span class=\"o\">=</span>datetime<span class=\"o\">.</span>datetime<span class=\"o\">.</span>now<span class=\"p\">)</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n<p>If the front page, displaying the latest blog entries, only changes when you\nadd a new blog entry, you can compute the last modified time very quickly. You\nneed the latest <code class=\"docutils literal notranslate\">published</code> date for every entry associated with that blog.\nOne way to do this would be:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">def</span> <span class=\"nf\">latest_entry</span><span class=\"p\">(</span>request<span class=\"p\">,</span> blog_id<span class=\"p\">):</span>\n    <span class=\"k\">return</span> Entry<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>blog<span class=\"o\">=</span>blog_id<span class=\"p\">)</span><span class=\"o\">.</span>latest<span class=\"p\">(</span><span class=\"s2\">&quot;published&quot;</span><span class=\"p\">)</span><span class=\"o\">.</span>published\n</code></pre></div>\n<p>You can then use this function to provide early detection of an unchanged page\nfor your front page view:</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.http</span> <span class=\"kn\">import</span> condition\n\n<span class=\"nd\">@condition</span><span class=\"p\">(</span>last_modified_func<span class=\"o\">=</span>latest_entry<span class=\"p\">)</span>\n<span class=\"k\">def</span> <span class=\"nf\">front_page</span><span class=\"p\">(</span>request<span class=\"p\">,</span> blog_id<span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n<aside class=\"admonition-be-careful-with-the-order-of-decorators admonition\" role=\"note\">\n<p class=\"admonition-title\">デコレータの順番に注意</p>\n<p>When <code class=\"docutils literal notranslate\">condition()</code> returns a conditional response, any decorators below\nit will be skipped and won't apply to the response. Therefore, any\ndecorators that need to apply to both the regular view response and a\nconditional response must be above <code class=\"docutils literal notranslate\">condition()</code>. In particular,\n<a class=\"reference internal\" href=\"/ja/3.2/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>,\n<a class=\"reference internal\" href=\"/ja/3.2/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>, and\n<a class=\"reference internal\" href=\"/ja/3.2/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> should come first\nbecause <span class=\"target\" id=\"index-6\"></span><a class=\"rfc reference external\" href=\"https://datatracker.ietf.org/doc/html/rfc7232.html#section-4.1\"><strong>RFC 7232</strong></a> requires that the headers they\nset be present on 304 responses.</p>\n</aside>\n</section>\n<section id=\"shortcuts-for-only-computing-one-value\">\n<h2>1つの値を計算するだけのショートカット<a class=\"heading-anchor\" href=\"#shortcuts-for-only-computing-one-value\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>As a general rule, if you can provide functions to compute <em>both</em> the ETag and\nthe last modified time, you should do so. You don't know which headers any\ngiven HTTP client will send you, so be prepared to handle both. However,\nsometimes only one value is easy to compute and Django provides decorators\nthat handle only ETag or only last-modified computations.</p>\n<p>The <code class=\"docutils literal notranslate\">django.views.decorators.http.etag</code> and\n<code class=\"docutils literal notranslate\">django.views.decorators.http.last_modified</code> decorators are passed the same\ntype of functions as the <code class=\"docutils literal notranslate\">condition</code> decorator. Their signatures are:</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>etag<span class=\"p\">(</span>etag_func<span class=\"p\">)</span>\nlast_modified<span class=\"p\">(</span>last_modified_func<span class=\"p\">)</span>\n</code></pre></div>\n<p>We could write the earlier example, which only uses a last-modified function,\nusing one of these decorators:</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=\"nd\">@last_modified</span><span class=\"p\">(</span>latest_entry<span class=\"p\">)</span>\n<span class=\"k\">def</span> <span class=\"nf\">front_page</span><span class=\"p\">(</span>request<span class=\"p\">,</span> blog_id<span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\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=\"k\">def</span> <span class=\"nf\">front_page</span><span class=\"p\">(</span>request<span class=\"p\">,</span> blog_id<span class=\"p\">):</span>\n    <span class=\"o\">...</span>\nfront_page <span class=\"o\">=</span> last_modified<span class=\"p\">(</span>latest_entry<span class=\"p\">)(</span>front_page<span class=\"p\">)</span>\n</code></pre></div>\n<section id=\"use-condition-when-testing-both-conditions\">\n<h3>2つの条件をテストする場合に <code class=\"docutils literal notranslate\">condition</code> を使う<a class=\"heading-anchor\" href=\"#use-condition-when-testing-both-conditions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>It might look nicer to some people to try and chain the <code class=\"docutils literal notranslate\">etag</code> and\n<code class=\"docutils literal notranslate\">last_modified</code> decorators if you want to test both preconditions. However,\nthis would lead to incorrect behavior.</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=\"c1\"># Bad code. Don&#39;t do this!</span>\n<span class=\"nd\">@etag</span><span class=\"p\">(</span>etag_func<span class=\"p\">)</span>\n<span class=\"nd\">@last_modified</span><span class=\"p\">(</span>last_modified_func<span class=\"p\">)</span>\n<span class=\"k\">def</span> <span class=\"nf\">my_view</span><span class=\"p\">(</span>request<span class=\"p\">):</span>\n    <span class=\"c1\"># ...</span>\n\n<span class=\"c1\"># End of bad code.</span>\n</code></pre></div>\n<p>The first decorator doesn't know anything about the second and might\nanswer that the response is not modified even if the second decorators would\ndetermine otherwise. The <code class=\"docutils literal notranslate\">condition</code> decorator uses both callback functions\nsimultaneously to work out the right action to take.</p>\n</section>\n</section>\n<section id=\"using-the-decorators-with-other-http-methods\">\n<h2>その他の HTTP メソッドでデコレータを使用する<a class=\"heading-anchor\" href=\"#using-the-decorators-with-other-http-methods\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>The <code class=\"docutils literal notranslate\">condition</code> decorator is useful for more than only <code class=\"docutils literal notranslate\">GET</code> and\n<code class=\"docutils literal notranslate\">HEAD</code> requests (<code class=\"docutils literal notranslate\">HEAD</code> requests are the same as <code class=\"docutils literal notranslate\">GET</code> in this\nsituation). It can also be used to provide checking for <code class=\"docutils literal notranslate\">POST</code>,\n<code class=\"docutils literal notranslate\">PUT</code> and <code class=\"docutils literal notranslate\">DELETE</code> requests. In these situations, the idea isn't to return\na &quot;not modified&quot; response, but to tell the client that the resource they are\ntrying to change has been altered in the meantime.</p>\n<p>たとえば、つぎのようなクライアントとサーバを交換する例を考えてみてください。</p>\n<ol class=\"arabic simple\">\n<li><p>クライアントが <code class=\"docutils literal notranslate\">/foo/</code> をリクエストします。</p></li>\n<li><p>サーバーは何らかのコンテンツを <code class=\"docutils literal notranslate\">&quot;abcd1234&quot;</code> という ETag を付けて返します。</p></li>\n<li><p>Client sends an HTTP <code class=\"docutils literal notranslate\">PUT</code> request to <code class=\"docutils literal notranslate\">/foo/</code> to update the\nresource. It also sends an <code class=\"docutils literal notranslate\">If-Match: &quot;abcd1234&quot;</code> header to specify\nthe version it is trying to update.</p></li>\n<li><p>Server checks to see if the resource has changed, by computing the ETag\nthe same way it does for a <code class=\"docutils literal notranslate\">GET</code> request (using the same function).\nIf the resource <em>has</em> changed, it will return a 412 status code,\nmeaning &quot;precondition failed&quot;.</p></li>\n<li><p>Client sends a <code class=\"docutils literal notranslate\">GET</code> request to <code class=\"docutils literal notranslate\">/foo/</code>, after receiving a 412\nresponse, to retrieve an updated version of the content before updating\nit.</p></li>\n</ol>\n<p>The important thing this example shows is that the same functions can be used\nto compute the ETag and last modification values in all situations. In fact,\nyou <strong>should</strong> use the same functions, so that the same values are returned\nevery time.</p>\n<aside class=\"admonition-validator-headers-with-non-safe-request-methods admonition\" role=\"note\">\n<p class=\"admonition-title\">Validator headers with non-safe request methods</p>\n<p>The <code class=\"docutils literal notranslate\">condition</code> decorator only sets validator headers (<code class=\"docutils literal notranslate\">ETag</code> and\n<code class=\"docutils literal notranslate\">Last-Modified</code>) for safe HTTP methods, i.e. <code class=\"docutils literal notranslate\">GET</code> and <code class=\"docutils literal notranslate\">HEAD</code>. If you\nwish to return them in other cases, set them in your view. See\n<span class=\"target\" id=\"index-7\"></span><a class=\"rfc reference external\" href=\"https://datatracker.ietf.org/doc/html/rfc7231.html#section-4.3.4\"><strong>RFC 7231 Section 4.3.4</strong></a> to learn about the distinction between setting a\nvalidator header in response to requests made with <code class=\"docutils literal notranslate\">PUT</code> versus <code class=\"docutils literal notranslate\">POST</code>.</p>\n</aside>\n</section>\n<section id=\"comparison-with-middleware-conditional-processing\">\n<h2>Comparison with middleware conditional processing<a class=\"heading-anchor\" href=\"#comparison-with-middleware-conditional-processing\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Django provides conditional <code class=\"docutils literal notranslate\">GET</code> handling via\n<a class=\"reference internal\" href=\"/ja/3.2/ref/middleware/#django.middleware.http.ConditionalGetMiddleware\" title=\"django.middleware.http.ConditionalGetMiddleware\"><code class=\"xref py py-class docutils literal notranslate\">django.middleware.http.ConditionalGetMiddleware</code></a>. While being suitable\nfor many situations, the middleware has limitations for advanced usage:</p>\n<ul class=\"simple\">\n<li><p>It's applied globally to all views in your project.</p></li>\n<li><p>It doesn't save you from generating the response, which may be expensive.</p></li>\n<li><p>これが適切なのは、HTTP の <code class=\"docutils literal notranslate\">GET</code> リクエストに対してのみです。</p></li>\n</ul>\n<p>You should choose the most appropriate tool for your particular problem here.\nIf you have a way to compute ETags and modification times quickly and if some\nview takes a while to generate the content, you should consider using the\n<code class=\"docutils literal notranslate\">condition</code> decorator described in this document. If everything already runs\nfairly quickly, stick to using the middleware and the amount of network\ntraffic sent back to the clients will still be reduced if the view hasn't\nchanged.</p>\n</section>","rootId":"conditional-view-processing","toc":[{"title":"condition デコレータ","anchor":"the-condition-decorator","children":[]},{"title":"1つの値を計算するだけのショートカット","anchor":"shortcuts-for-only-computing-one-value","children":[{"title":"2つの条件をテストする場合に condition を使う","anchor":"use-condition-when-testing-both-conditions","children":[]}]},{"title":"その他の HTTP メソッドでデコレータを使用する","anchor":"using-the-decorators-with-other-http-methods","children":[]},{"title":"Comparison with middleware conditional processing","anchor":"comparison-with-middleware-conditional-processing","children":[]}],"breadcrumbs":[{"docname":"topics/index","title":"Django を使う","url":"/ja/3.2/topics/"}],"prev":{"docname":"topics/cache","title":"Django's cache framework","url":"/ja/3.2/topics/cache/"},"next":{"docname":"topics/signing","title":"暗号署名","url":"/ja/3.2/topics/signing/"},"formats":{"html":"/ja/3.2/topics/conditional-view-processing/","markdown":"/ja/3.2/topics/conditional-view-processing.md","json":"/ja/3.2/topics/conditional-view-processing.json"},"source":"https://github.com/django/django/blob/stable/3.2.x/docs/topics/conditional-view-processing.txt","official":"https://docs.djangoproject.com/ja/3.2/topics/conditional-view-processing/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0","1.11","1.10","1.9"],"inLocales":["en","zh-hans","fr","ja","id","it","pt-br","ko","es","el","pl"]}