{"title":"クラスベースビュー入門","version":"3.0","locale":"ja","docname":"topics/class-based-views/intro","url":"/ja/3.0/topics/class-based-views/intro/","canonical":"https://djangodocs.dev/ja/3.0/topics/class-based-views/intro/","summary":"クラスベースビューはビューを実装するもう一つの手段で、関数の代わりに Python のオブジェクトとしてビューを定義します。","html":"<h1>クラスベースビュー入門<a class=\"heading-anchor\" href=\"#introduction-to-class-based-views\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>クラスベースビューはビューを実装するもう一つの手段で、関数の代わりに Python のオブジェクトとしてビューを定義します。クラスベースビューは関数ベースのビューを完全に置き換えるものではありませんが、関数ベースのビューと比較して、以下のような違いと利点があります。</p>\n<ul class=\"simple\">\n<li><p>特定の HTTP メソッド (<code class=\"docutils literal notranslate\">GET</code>、<code class=\"docutils literal notranslate\">POST</code> など) に関連するコードの集まりを、条件分岐を使ってかき分けるのではなく、それぞれに独立したメソッドを割り当てることができる。</p></li>\n<li><p>ミックスイン (多重継承) などのオブジェクト指向のテクニックを使って、コードを再利用可能なコンポーネントに分解できる。</p></li>\n</ul>\n<section id=\"the-relationship-and-history-of-generic-views-class-based-views-and-class-based-generic-views\">\n<h2>ジェネリックビュー、クラスベースビュー、クラスベースジェネリックビューの関係と歴史的経緯<a class=\"heading-anchor\" href=\"#the-relationship-and-history-of-generic-views-class-based-views-and-class-based-generic-views\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>まず初めに存在したのは、ビュー関数の規約だけでした。Django は、定義された関数に <a class=\"reference internal\" href=\"/ja/3.0/ref/request-response/#django.http.HttpRequest\" title=\"django.http.HttpRequest\"><code class=\"xref py py-class docutils literal notranslate\">HttpRequest</code></a> を渡して、<a class=\"reference internal\" href=\"/ja/3.0/ref/request-response/#django.http.HttpResponse\" title=\"django.http.HttpResponse\"><code class=\"xref py py-class docutils literal notranslate\">HttpResponse</code></a> が返ってくることを期待していました。Django が提供する機能はこの範囲まででした。</p>\n<p>早い内に、ビューの開発には共通のイディオムやパターンが存在することが認識されるようになりました。こうしたパターンを抽象化し、共通ケースに当てはまるようなビューの開発を楽にするために導入されたのが、関数ベースのジェネリックビューでした。</p>\n<p>The problem with function-based generic views is that while they covered the\nsimple cases well, there was no way to extend or customize them beyond some\nconfiguration options, limiting their usefulness in many real-world\napplications.</p>\n<p>クラスベースのジェネリックビューは関数ベースのジェネリックビューと同様に、ビューの開発を楽にすることを目的に作成されました。しかし、ミックスインを使用するなどの実装方法の工夫により、ツールキットを提供することができ、結果として、関数ベースのジェネリックビューに比べて、より拡張性が高く、柔軟なものにすることができました。</p>\n<p>If you have tried function based generic views in the past and found them\nlacking, you should not think of class-based generic views as a class-based\nequivalent, but rather as a fresh approach to solving the original problems\nthat generic views were meant to solve.</p>\n<p>The toolkit of base classes and mixins that Django uses to build class-based\ngeneric views are built for maximum flexibility, and as such have many hooks in\nthe form of default method implementations and attributes that you are unlikely\nto be concerned with in the simplest use cases. For example, instead of\nlimiting you to a class-based attribute for <code class=\"docutils literal notranslate\">form_class</code>, the implementation\nuses a <code class=\"docutils literal notranslate\">get_form</code> method, which calls a <code class=\"docutils literal notranslate\">get_form_class</code> method, which in\nits default implementation returns the <code class=\"docutils literal notranslate\">form_class</code> attribute of the class.\nThis gives you several options for specifying what form to use, from an\nattribute, to a fully dynamic, callable hook. These options seem to add hollow\ncomplexity for simple situations, but without them, more advanced designs would\nbe limited.</p>\n</section>\n<section id=\"using-class-based-views\">\n<h2>クラスベースのビューを使用する<a class=\"heading-anchor\" href=\"#using-class-based-views\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>中核となる機能として、クラスベースのビューでは、HTTP リクエストのメソッドに応じてクラスインスタンスの異なるメソッドを呼び出させることができるため、1つのビュー関数の内部で条件分岐を使わずにすみます。</p>\n<p>そのため、ビュー関数の場合に HTTP <code class=\"docutils literal notranslate\">GET</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\">from</span> <span class=\"nn\">django.http</span> <span class=\"kn\">import</span> HttpResponse\n\n<span class=\"k\">def</span> <span class=\"nf\">my_view</span><span class=\"p\">(</span>request<span class=\"p\">):</span>\n    <span class=\"k\">if</span> request<span class=\"o\">.</span>method <span class=\"o\">==</span> <span class=\"s1\">&#39;GET&#39;</span><span class=\"p\">:</span>\n        <span class=\"c1\"># &lt;view logic&gt;</span>\n        <span class=\"k\">return</span> HttpResponse<span class=\"p\">(</span><span class=\"s1\">&#39;result&#39;</span><span class=\"p\">)</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=\"kn\">from</span> <span class=\"nn\">django.http</span> <span class=\"kn\">import</span> HttpResponse\n<span class=\"kn\">from</span> <span class=\"nn\">django.views</span> <span class=\"kn\">import</span> View\n\n<span class=\"k\">class</span> <span class=\"nc\">MyView</span><span class=\"p\">(</span>View<span class=\"p\">):</span>\n    <span class=\"k\">def</span> <span class=\"nf\">get</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> request<span class=\"p\">):</span>\n        <span class=\"c1\"># &lt;view logic&gt;</span>\n        <span class=\"k\">return</span> HttpResponse<span class=\"p\">(</span><span class=\"s1\">&#39;result&#39;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Because Django's URL resolver expects to send the request and associated\narguments to a callable function, not a class, class-based views have an\n<a class=\"reference internal\" href=\"/ja/3.0/ref/class-based-views/base/#django.views.generic.base.View.as_view\" title=\"django.views.generic.base.View.as_view\"><code class=\"xref py py-meth docutils literal notranslate\">as_view()</code></a> class method which returns a\nfunction that can be called when a request arrives for a URL matching the\nassociated pattern. The function creates an instance of the class, calls\n<a class=\"reference internal\" href=\"/ja/3.0/ref/class-based-views/base/#django.views.generic.base.View.setup\" title=\"django.views.generic.base.View.setup\"><code class=\"xref py py-meth docutils literal notranslate\">setup()</code></a> to initialize its attributes, and\nthen calls its <a class=\"reference internal\" href=\"/ja/3.0/ref/class-based-views/base/#django.views.generic.base.View.dispatch\" title=\"django.views.generic.base.View.dispatch\"><code class=\"xref py py-meth docutils literal notranslate\">dispatch()</code></a> method.\n<code class=\"docutils literal notranslate\">dispatch</code> looks at the request to determine whether it is a <code class=\"docutils literal notranslate\">GET</code>,\n<code class=\"docutils literal notranslate\">POST</code>, etc, and relays the request to a matching method if one is defined,\nor raises <a class=\"reference internal\" href=\"/ja/3.0/ref/request-response/#django.http.HttpResponseNotAllowed\" title=\"django.http.HttpResponseNotAllowed\"><code class=\"xref py py-class docutils literal notranslate\">HttpResponseNotAllowed</code></a> if not:</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\"># urls.py</span>\n<span class=\"kn\">from</span> <span class=\"nn\">django.urls</span> <span class=\"kn\">import</span> path\n<span class=\"kn\">from</span> <span class=\"nn\">myapp.views</span> <span class=\"kn\">import</span> MyView\n\nurlpatterns <span class=\"o\">=</span> <span class=\"p\">[</span>\n    path<span class=\"p\">(</span><span class=\"s1\">&#39;about/&#39;</span><span class=\"p\">,</span> MyView<span class=\"o\">.</span>as_view<span class=\"p\">()),</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>メソッドが関数ベースのビューが返すもの、つまり何らかの形の <a class=\"reference internal\" href=\"/ja/3.0/ref/request-response/#django.http.HttpResponse\" title=\"django.http.HttpResponse\"><code class=\"xref py py-class docutils literal notranslate\">HttpResponse</code></a> と同等のものしか返せないなら意味はありません。これが意味するのは、<span class=\"xref std std-doc\">http shortcuts ` や :class:`~django.template.response.TemplateResponse</span> オブジェクトはクラスベースのビューの内部でも使えるということです。</p>\n<p>最小限のクラスベースのビューでは、ジョブを実行するのにどんなクラス属性も必要としませんが、クラスベースの設計をする場合にはクラス属性が役に立つことが多いです。クラス属性のカスタマイズと設定を行うには2つの方法があります。</p>\n<p>第1の方法は、通常の Python のサブクラス化を行い、サブクラス上で属性やメソッドを上書きするという方法です。たとえば、次のように親クラスが <code class=\"docutils literal notranslate\">greeting</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\">from</span> <span class=\"nn\">django.http</span> <span class=\"kn\">import</span> HttpResponse\n<span class=\"kn\">from</span> <span class=\"nn\">django.views</span> <span class=\"kn\">import</span> View\n\n<span class=\"k\">class</span> <span class=\"nc\">GreetingView</span><span class=\"p\">(</span>View<span class=\"p\">):</span>\n    greeting <span class=\"o\">=</span> <span class=\"s2\">&quot;Good Day&quot;</span>\n\n    <span class=\"k\">def</span> <span class=\"nf\">get</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> request<span class=\"p\">):</span>\n        <span class=\"k\">return</span> HttpResponse<span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span>greeting<span class=\"p\">)</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\">class</span> <span class=\"nc\">MorningGreetingView</span><span class=\"p\">(</span>GreetingView<span class=\"p\">):</span>\n    greeting <span class=\"o\">=</span> <span class=\"s2\">&quot;Morning to ya&quot;</span>\n</code></pre></div>\n<p>もう一つの方法は、URLconf 内での <a class=\"reference internal\" href=\"/ja/3.0/ref/class-based-views/base/#django.views.generic.base.View.as_view\" title=\"django.views.generic.base.View.as_view\"><code class=\"xref py py-meth docutils literal notranslate\">as_view()</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>urlpatterns <span class=\"o\">=</span> <span class=\"p\">[</span>\n    path<span class=\"p\">(</span><span class=\"s1\">&#39;about/&#39;</span><span class=\"p\">,</span> GreetingView<span class=\"o\">.</span>as_view<span class=\"p\">(</span>greeting<span class=\"o\">=</span><span class=\"s2\">&quot;G&#39;day&quot;</span><span class=\"p\">)),</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">注釈</p>\n<p>定義したクラスはリクエストが発行されるごとにインスタンス化されますが、<a class=\"reference internal\" href=\"/ja/3.0/ref/class-based-views/base/#django.views.generic.base.View.as_view\" title=\"django.views.generic.base.View.as_view\"><code class=\"xref py py-meth docutils literal notranslate\">as_view()</code></a> エントリーポイントで指定したクラス属性が設定されるのは、URL がインポートされる際の1回だけです。</p>\n</aside>\n</section>\n<section id=\"using-mixins\">\n<h2>ミックスインを使用する<a class=\"heading-anchor\" href=\"#using-mixins\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>ミックスインは、複数の親クラスのメソッドや属性を混合することができる多重継承の形式の1つです。</p>\n<p>For example, in the generic class-based views there is a mixin called\n<a class=\"reference internal\" href=\"/ja/3.0/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin\" title=\"django.views.generic.base.TemplateResponseMixin\"><code class=\"xref py py-class docutils literal notranslate\">TemplateResponseMixin</code></a> whose primary purpose\nis to define the method\n<a class=\"reference internal\" href=\"/ja/3.0/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin.render_to_response\" title=\"django.views.generic.base.TemplateResponseMixin.render_to_response\"><code class=\"xref py py-meth docutils literal notranslate\">render_to_response()</code></a>.\nWhen combined with the behavior of the <a class=\"reference internal\" href=\"/ja/3.0/ref/class-based-views/base/#django.views.generic.base.View\" title=\"django.views.generic.base.View\"><code class=\"xref py py-class docutils literal notranslate\">View</code></a>\nbase class, the result is a <a class=\"reference internal\" href=\"/ja/3.0/ref/class-based-views/base/#django.views.generic.base.TemplateView\" title=\"django.views.generic.base.TemplateView\"><code class=\"xref py py-class docutils literal notranslate\">TemplateView</code></a>\nclass that will dispatch requests to the appropriate matching methods (a\nbehavior defined in the <code class=\"docutils literal notranslate\">View</code> base class), and that has a\n<a class=\"reference internal\" href=\"/ja/3.0/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin.render_to_response\" title=\"django.views.generic.base.TemplateResponseMixin.render_to_response\"><code class=\"xref py py-meth docutils literal notranslate\">render_to_response()</code></a>\nmethod that uses a\n<a class=\"reference internal\" href=\"/ja/3.0/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin.template_name\" title=\"django.views.generic.base.TemplateResponseMixin.template_name\"><code class=\"xref py py-attr docutils literal notranslate\">template_name</code></a>\nattribute to return a <a class=\"reference internal\" href=\"/ja/3.0/ref/template-response/#django.template.response.TemplateResponse\" title=\"django.template.response.TemplateResponse\"><code class=\"xref py py-class docutils literal notranslate\">TemplateResponse</code></a>\nobject (a behavior defined in the <code class=\"docutils literal notranslate\">TemplateResponseMixin</code>).</p>\n<p>Mixins are an excellent way of reusing code across multiple classes, but they\ncome with some cost. The more your code is scattered among mixins, the harder\nit will be to read a child class and know what exactly it is doing, and the\nharder it will be to know which methods from which mixins to override if you\nare subclassing something that has a deep inheritance tree.</p>\n<p>Note also that you can only inherit from one generic view - that is, only one\nparent class may inherit from <a class=\"reference internal\" href=\"/ja/3.0/ref/class-based-views/base/#django.views.generic.base.View\" title=\"django.views.generic.base.View\"><code class=\"xref py py-class docutils literal notranslate\">View</code></a> and\nthe rest (if any) should be mixins. Trying to inherit from more than one class\nthat inherits from <code class=\"docutils literal notranslate\">View</code> - for example, trying to use a form at the top of a\nlist and combining <a class=\"reference internal\" href=\"/ja/3.0/ref/class-based-views/mixins-editing/#django.views.generic.edit.ProcessFormView\" title=\"django.views.generic.edit.ProcessFormView\"><code class=\"xref py py-class docutils literal notranslate\">ProcessFormView</code></a> and\n<a class=\"reference internal\" href=\"/ja/3.0/ref/class-based-views/generic-display/#django.views.generic.list.ListView\" title=\"django.views.generic.list.ListView\"><code class=\"xref py py-class docutils literal notranslate\">ListView</code></a> - won't work as expected.</p>\n</section>\n<section id=\"handling-forms-with-class-based-views\">\n<h2>クラスベースのビューでフォームを扱う<a class=\"heading-anchor\" href=\"#handling-forms-with-class-based-views\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\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.http</span> <span class=\"kn\">import</span> HttpResponseRedirect\n<span class=\"kn\">from</span> <span class=\"nn\">django.shortcuts</span> <span class=\"kn\">import</span> render\n\n<span class=\"kn\">from</span> <span class=\"nn\">.forms</span> <span class=\"kn\">import</span> MyForm\n\n<span class=\"k\">def</span> <span class=\"nf\">myview</span><span class=\"p\">(</span>request<span class=\"p\">):</span>\n    <span class=\"k\">if</span> request<span class=\"o\">.</span>method <span class=\"o\">==</span> <span class=\"s2\">&quot;POST&quot;</span><span class=\"p\">:</span>\n        form <span class=\"o\">=</span> MyForm<span class=\"p\">(</span>request<span class=\"o\">.</span>POST<span class=\"p\">)</span>\n        <span class=\"k\">if</span> form<span class=\"o\">.</span>is_valid<span class=\"p\">():</span>\n            <span class=\"c1\"># &lt;process form cleaned data&gt;</span>\n            <span class=\"k\">return</span> HttpResponseRedirect<span class=\"p\">(</span><span class=\"s1\">&#39;/success/&#39;</span><span class=\"p\">)</span>\n    <span class=\"k\">else</span><span class=\"p\">:</span>\n        form <span class=\"o\">=</span> MyForm<span class=\"p\">(</span>initial<span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s1\">&#39;key&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;value&#39;</span><span class=\"p\">})</span>\n\n    <span class=\"k\">return</span> render<span class=\"p\">(</span>request<span class=\"p\">,</span> <span class=\"s1\">&#39;form_template.html&#39;</span><span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s1\">&#39;form&#39;</span><span class=\"p\">:</span> form<span class=\"p\">})</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=\"kn\">from</span> <span class=\"nn\">django.http</span> <span class=\"kn\">import</span> HttpResponseRedirect\n<span class=\"kn\">from</span> <span class=\"nn\">django.shortcuts</span> <span class=\"kn\">import</span> render\n<span class=\"kn\">from</span> <span class=\"nn\">django.views</span> <span class=\"kn\">import</span> View\n\n<span class=\"kn\">from</span> <span class=\"nn\">.forms</span> <span class=\"kn\">import</span> MyForm\n\n<span class=\"k\">class</span> <span class=\"nc\">MyFormView</span><span class=\"p\">(</span>View<span class=\"p\">):</span>\n    form_class <span class=\"o\">=</span> MyForm\n    initial <span class=\"o\">=</span> <span class=\"p\">{</span><span class=\"s1\">&#39;key&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;value&#39;</span><span class=\"p\">}</span>\n    template_name <span class=\"o\">=</span> <span class=\"s1\">&#39;form_template.html&#39;</span>\n\n    <span class=\"k\">def</span> <span class=\"nf\">get</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> request<span class=\"p\">,</span> <span class=\"o\">*</span>args<span class=\"p\">,</span> <span class=\"o\">**</span>kwargs<span class=\"p\">):</span>\n        form <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span>form_class<span class=\"p\">(</span>initial<span class=\"o\">=</span><span class=\"bp\">self</span><span class=\"o\">.</span>initial<span class=\"p\">)</span>\n        <span class=\"k\">return</span> render<span class=\"p\">(</span>request<span class=\"p\">,</span> <span class=\"bp\">self</span><span class=\"o\">.</span>template_name<span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s1\">&#39;form&#39;</span><span class=\"p\">:</span> form<span class=\"p\">})</span>\n\n    <span class=\"k\">def</span> <span class=\"nf\">post</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> request<span class=\"p\">,</span> <span class=\"o\">*</span>args<span class=\"p\">,</span> <span class=\"o\">**</span>kwargs<span class=\"p\">):</span>\n        form <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span>form_class<span class=\"p\">(</span>request<span class=\"o\">.</span>POST<span class=\"p\">)</span>\n        <span class=\"k\">if</span> form<span class=\"o\">.</span>is_valid<span class=\"p\">():</span>\n            <span class=\"c1\"># &lt;process form cleaned data&gt;</span>\n            <span class=\"k\">return</span> HttpResponseRedirect<span class=\"p\">(</span><span class=\"s1\">&#39;/success/&#39;</span><span class=\"p\">)</span>\n\n        <span class=\"k\">return</span> render<span class=\"p\">(</span>request<span class=\"p\">,</span> <span class=\"bp\">self</span><span class=\"o\">.</span>template_name<span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s1\">&#39;form&#39;</span><span class=\"p\">:</span> form<span class=\"p\">})</span>\n</code></pre></div>\n<p>This is a minimal case, but you can see that you would then have the option\nof customizing this view by overriding any of the class attributes, e.g.\n<code class=\"docutils literal notranslate\">form_class</code>, via URLconf configuration, or subclassing and overriding one or\nmore of the methods (or both!).</p>\n</section>\n<section id=\"decorating-class-based-views\">\n<h2>クラスベースのビューをデコレーションする<a class=\"heading-anchor\" href=\"#decorating-class-based-views\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>クラスベースのビューを拡張する方法は、ミックスインの使用にとどまりません。デコレータも使用できます。クラスベースのビューは関数ではないので、<code class=\"docutils literal notranslate\">as_view()</code> を使用した場合とサブクラスを作成した場合では、デコレータは違った動作をします。</p>\n<section id=\"decorating-in-urlconf\">\n<h3>URLconf でデコレーションする<a class=\"heading-anchor\" href=\"#decorating-in-urlconf\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>You can adjust class-based views by decorating the result of the\n<a class=\"reference internal\" href=\"/ja/3.0/ref/class-based-views/base/#django.views.generic.base.View.as_view\" title=\"django.views.generic.base.View.as_view\"><code class=\"xref py py-meth docutils literal notranslate\">as_view()</code></a> method. The easiest place to do\nthis is in the URLconf where you deploy your 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.contrib.auth.decorators</span> <span class=\"kn\">import</span> login_required<span class=\"p\">,</span> permission_required\n<span class=\"kn\">from</span> <span class=\"nn\">django.views.generic</span> <span class=\"kn\">import</span> TemplateView\n\n<span class=\"kn\">from</span> <span class=\"nn\">.views</span> <span class=\"kn\">import</span> VoteView\n\nurlpatterns <span class=\"o\">=</span> <span class=\"p\">[</span>\n    path<span class=\"p\">(</span><span class=\"s1\">&#39;about/&#39;</span><span class=\"p\">,</span> login_required<span class=\"p\">(</span>TemplateView<span class=\"o\">.</span>as_view<span class=\"p\">(</span>template_name<span class=\"o\">=</span><span class=\"s2\">&quot;secret.html&quot;</span><span class=\"p\">))),</span>\n    path<span class=\"p\">(</span><span class=\"s1\">&#39;vote/&#39;</span><span class=\"p\">,</span> permission_required<span class=\"p\">(</span><span class=\"s1\">&#39;polls.can_vote&#39;</span><span class=\"p\">)(</span>VoteView<span class=\"o\">.</span>as_view<span class=\"p\">())),</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>このアプローチではデコレータはインスタンスごとに適用されます。もしあるビューのすべてのインスタンスをデコレーションしたいばあいは、別のアプローチを取る必要があります。</p>\n</section>\n<section id=\"decorating-the-class\">\n<span id=\"id1\"></span><h3>クラスをデコレーションする<a class=\"heading-anchor\" href=\"#decorating-the-class\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>クラスベースのビューのすべてのインスタンスをデコレーションするには、クラスの定義自体をデコレーションする必要があります。そのためには、クラスの <a class=\"reference internal\" href=\"/ja/3.0/ref/class-based-views/base/#django.views.generic.base.View.dispatch\" title=\"django.views.generic.base.View.dispatch\"><code class=\"xref py py-meth docutils literal notranslate\">dispatch()</code></a> メソッドにデコレータを付けます。</p>\n<p>クラス上のメソッドはスタンドアロンの関数と完全に同じではないため、関数デコレータを単純にそのままメソッドに適用することはできません。適用前にメソッドデコレータに変換する必要があります。<code class=\"docutils literal notranslate\">method_decorator</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\">from</span> <span class=\"nn\">django.contrib.auth.decorators</span> <span class=\"kn\">import</span> login_required\n<span class=\"kn\">from</span> <span class=\"nn\">django.utils.decorators</span> <span class=\"kn\">import</span> method_decorator\n<span class=\"kn\">from</span> <span class=\"nn\">django.views.generic</span> <span class=\"kn\">import</span> TemplateView\n\n<span class=\"k\">class</span> <span class=\"nc\">ProtectedView</span><span class=\"p\">(</span>TemplateView<span class=\"p\">):</span>\n    template_name <span class=\"o\">=</span> <span class=\"s1\">&#39;secret.html&#39;</span>\n\n    <span class=\"nd\">@method_decorator</span><span class=\"p\">(</span>login_required<span class=\"p\">)</span>\n    <span class=\"k\">def</span> <span class=\"nf\">dispatch</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"o\">*</span>args<span class=\"p\">,</span> <span class=\"o\">**</span>kwargs<span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span>dispatch<span class=\"p\">(</span><span class=\"o\">*</span>args<span class=\"p\">,</span> <span class=\"o\">**</span>kwargs<span class=\"p\">)</span>\n</code></pre></div>\n<p>あるいは、より簡潔に、クラスを代わりにデコレートして、デコレーション対象のメソッド名をキーワード引数 <code class=\"docutils literal notranslate\">name</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=\"nd\">@method_decorator</span><span class=\"p\">(</span>login_required<span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s1\">&#39;dispatch&#39;</span><span class=\"p\">)</span>\n<span class=\"k\">class</span> <span class=\"nc\">ProtectedView</span><span class=\"p\">(</span>TemplateView<span class=\"p\">):</span>\n    template_name <span class=\"o\">=</span> <span class=\"s1\">&#39;secret.html&#39;</span>\n</code></pre></div>\n<p>共通のデコレータ群が複数の場所で呼ばれる場合には、デコレータのリストまたはタプルを定義して、これを <code class=\"docutils literal notranslate\">method_decorator()</code> を複数回呼ぶ代わりに使用できます。以下の2つのクラスは同じになります。</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>decorators <span class=\"o\">=</span> <span class=\"p\">[</span>never_cache<span class=\"p\">,</span> login_required<span class=\"p\">]</span>\n\n<span class=\"nd\">@method_decorator</span><span class=\"p\">(</span>decorators<span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s1\">&#39;dispatch&#39;</span><span class=\"p\">)</span>\n<span class=\"k\">class</span> <span class=\"nc\">ProtectedView</span><span class=\"p\">(</span>TemplateView<span class=\"p\">):</span>\n    template_name <span class=\"o\">=</span> <span class=\"s1\">&#39;secret.html&#39;</span>\n\n<span class=\"nd\">@method_decorator</span><span class=\"p\">(</span>never_cache<span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s1\">&#39;dispatch&#39;</span><span class=\"p\">)</span>\n<span class=\"nd\">@method_decorator</span><span class=\"p\">(</span>login_required<span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s1\">&#39;dispatch&#39;</span><span class=\"p\">)</span>\n<span class=\"k\">class</span> <span class=\"nc\">ProtectedView</span><span class=\"p\">(</span>TemplateView<span class=\"p\">):</span>\n    template_name <span class=\"o\">=</span> <span class=\"s1\">&#39;secret.html&#39;</span>\n</code></pre></div>\n<p>デコレータは、デコレータに渡された順番でリクエストを処理します。上の例では、<code class=\"docutils literal notranslate\">never_cache()</code> が <code class=\"docutils literal notranslate\">login_required()</code> の前にリクエストを処理します。</p>\n<p>In this example, every instance of <code class=\"docutils literal notranslate\">ProtectedView</code> will have login\nprotection. These examples use <code class=\"docutils literal notranslate\">login_required</code>, however, the same behavior\ncan be obtained by using\n<a class=\"reference internal\" href=\"/ja/3.0/topics/auth/default/#django.contrib.auth.mixins.LoginRequiredMixin\" title=\"django.contrib.auth.mixins.LoginRequiredMixin\"><code class=\"xref py py-class docutils literal notranslate\">LoginRequiredMixin</code></a>.</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">注釈</p>\n<p><code class=\"docutils literal notranslate\">method_decorator</code> は、クラスのデコレートするメソッドに <code class=\"docutils literal notranslate\">*args</code> と <code class=\"docutils literal notranslate\">**kwargs</code> を引数として渡します。定義されているメソッドが互換性のある引数のセットを受け取れない場合には <code class=\"docutils literal notranslate\">TypeError</code> 例外が発生します。</p>\n</aside>\n</section>\n</section>","rootId":"introduction-to-class-based-views","toc":[{"title":"ジェネリックビュー、クラスベースビュー、クラスベースジェネリックビューの関係と歴史的経緯","anchor":"the-relationship-and-history-of-generic-views-class-based-views-and-class-based-generic-views","children":[]},{"title":"クラスベースのビューを使用する","anchor":"using-class-based-views","children":[]},{"title":"ミックスインを使用する","anchor":"using-mixins","children":[]},{"title":"クラスベースのビューでフォームを扱う","anchor":"handling-forms-with-class-based-views","children":[]},{"title":"クラスベースのビューをデコレーションする","anchor":"decorating-class-based-views","children":[{"title":"URLconf でデコレーションする","anchor":"decorating-in-urlconf","children":[]},{"title":"クラスをデコレーションする","anchor":"decorating-the-class","children":[]}]}],"breadcrumbs":[{"docname":"topics/index","title":"Django を使う","url":"/ja/3.0/topics/"},{"docname":"topics/class-based-views/index","title":"クラスベースビュー","url":"/ja/3.0/topics/class-based-views/"}],"prev":{"docname":"topics/class-based-views/index","title":"クラスベースビュー","url":"/ja/3.0/topics/class-based-views/"},"next":{"docname":"topics/class-based-views/generic-display","title":"ビルトインのクラスベースのジェネリックビュー","url":"/ja/3.0/topics/class-based-views/generic-display/"},"formats":{"html":"/ja/3.0/topics/class-based-views/intro/","markdown":"/ja/3.0/topics/class-based-views/intro.md","json":"/ja/3.0/topics/class-based-views/intro.json"},"source":"https://github.com/django/django/blob/stable/3.0.x/docs/topics/class-based-views/intro.txt","official":"https://docs.djangoproject.com/ja/3.0/topics/class-based-views/intro/","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","pt-br","ko","es","el","pl"]}