{"title":"組み込みのクラスベースのジェネリックビュー（汎用ビュー）","version":"5.1","locale":"ja","docname":"topics/class-based-views/generic-display","url":"/ja/5.1/topics/class-based-views/generic-display/","canonical":"https://djangodocs.dev/ja/5.1/topics/class-based-views/generic-display/","summary":"ウェブアプリケーションを書くのは、特定のパターンを何度も繰り返すことになるため、単調になりがちです。","html":"<h1>組み込みのクラスベースのジェネリックビュー（汎用ビュー）<a class=\"heading-anchor\" href=\"#built-in-class-based-generic-views\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>ウェブアプリケーションを書くのは、特定のパターンを何度も繰り返すことになるため、単調になりがちです。Django はモデルとテンプレート層で単調さを取り除くことを試みてきましたが、ウェブ開発者はビューレベルでもこの種の退屈な繰り返しを経験してきました。</p>\n<p>Django の <em>ジェネリックビュー（汎用ビュー）</em> は、この苦痛を軽減するために開発されました。ビューの開発には共通のイディオムとパターンが存在するため、それらを抽象化することで、共通のビューデータを少ないコードで素早く記述できます。</p>\n<p>私たちはオブジェクトのリスト表示のような特定の共通タスクを認識することで、<em>任意の</em> オブジェクトのリストを表示するコードを書きます。そして、対象のモデルを URLconf から追加の引数として渡します。</p>\n<p>Django のジェネリックビューを使うと、以下のことが可能になります。</p>\n<ul class=\"simple\">\n<li><p>オブジェクトのリストと、1つのオブジェクトに対する詳細ページの表示。カンファレンスを管理するアプリケーションを作っている場合、リストビューの例としては、<code class=\"docutils literal notranslate\">TalkListView</code> や <code class=\"docutils literal notranslate\">RegisteredUserListView</code> といったものが考えられます。1つのトークの情報を表示するページが、いわゆる「詳細」ビューの一例です。</p></li>\n<li><p>日付を基本とするオブジェクトと、年・月・日のアーカイブページ、関連する詳細ページと「最新」ページの表示。</p></li>\n<li><p>認可の有無に関わらず、ユーザーにオブジェクトの作成・更新・削除を許可する。</p></li>\n</ul>\n<p>これらのビューを総合すると、開発者が遭遇する最も一般的なタスクを実行するためのインターフェースが提供されます。</p>\n<section id=\"extending-generic-views\">\n<h2>ジェネリックビューを拡張する<a class=\"heading-anchor\" href=\"#extending-generic-views\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>言うまでもなく、ジェネリックビューは実質的に開発をスピードアップさせてくれます。しかし、多くのプロジェクトでは遅かれ早かれジェネリックビューだけでは十分ではなくなる瞬間が訪れます。実際、新しい Django 開発者から最もよく聞かれる質問は、幅広い状況に対処するためにジェネリックビューを拡張するにはどうすれば良いのか、というものです。</p>\n<p>これが、1.3リリースでジェネリックビューが再設計された理由の一つです。以前のビューは、オプションが目まぐるしく変化するビュー関数でした。現在では、ジェネリックビューを拡張する推奨の方法は、URLconfで大量の設定を渡すのではなく、サブクラス化し、属性やメソッドをオーバーライドする方法です。</p>\n<p>上で述べたように、ジェネリックビューには限界があります。自作のビューをジェネリックビューのサブクラスとして実装することに四苦八苦していると、それよりも自作のクラスベースまたは関数ベースのビューを使った方が効率的なのではないかと思うかもしれません。</p>\n<p>ジェネリックビューの例はサードパーティアプリケーションでも利用できます。あるいは、自分で必要に応じてアプリケーションを作ることもできます。</p>\n</section>\n<section id=\"generic-views-of-objects\">\n<h2>オブジェクトのジェネリックビュー<a class=\"heading-anchor\" href=\"#generic-views-of-objects\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p><a class=\"reference internal\" href=\"/ja/5.1/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> はたしかに便利ですが、Django のジェネリックビューが本当の輝きを見せるのは、データベース内のコンテンツを表示するビューを作成する時です。これは非常に一般的なタスクなので、Django はオブジェクトのリストと詳細ビューを非常に簡単に生成するための組み込みのジェネリックビューをいくつか用意しているのです。</p>\n<p>オブジェクトのリストや個々のオブジェクトを表示する例から見てみましょう。</p>\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=\"c1\"># models.py</span>\n<span class=\"kn\">from</span> <span class=\"nn\">django.db</span> <span class=\"kn\">import</span> models\n\n\n<span class=\"k\">class</span> <span class=\"nc\">Publisher</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    name <span class=\"o\">=</span> models<span class=\"o\">.</span>CharField<span class=\"p\">(</span>max_length<span class=\"o\">=</span><span class=\"mi\">30</span><span class=\"p\">)</span>\n    address <span class=\"o\">=</span> models<span class=\"o\">.</span>CharField<span class=\"p\">(</span>max_length<span class=\"o\">=</span><span class=\"mi\">50</span><span class=\"p\">)</span>\n    city <span class=\"o\">=</span> models<span class=\"o\">.</span>CharField<span class=\"p\">(</span>max_length<span class=\"o\">=</span><span class=\"mi\">60</span><span class=\"p\">)</span>\n    state_province <span class=\"o\">=</span> models<span class=\"o\">.</span>CharField<span class=\"p\">(</span>max_length<span class=\"o\">=</span><span class=\"mi\">30</span><span class=\"p\">)</span>\n    country <span class=\"o\">=</span> models<span class=\"o\">.</span>CharField<span class=\"p\">(</span>max_length<span class=\"o\">=</span><span class=\"mi\">50</span><span class=\"p\">)</span>\n    website <span class=\"o\">=</span> models<span class=\"o\">.</span>URLField<span class=\"p\">()</span>\n\n    <span class=\"k\">class</span> <span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        ordering <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s2\">&quot;-name&quot;</span><span class=\"p\">]</span>\n\n    <span class=\"k\">def</span> <span class=\"fm\">__str__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span>name\n\n\n<span class=\"k\">class</span> <span class=\"nc\">Author</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    salutation <span class=\"o\">=</span> models<span class=\"o\">.</span>CharField<span class=\"p\">(</span>max_length<span class=\"o\">=</span><span class=\"mi\">10</span><span class=\"p\">)</span>\n    name <span class=\"o\">=</span> models<span class=\"o\">.</span>CharField<span class=\"p\">(</span>max_length<span class=\"o\">=</span><span class=\"mi\">200</span><span class=\"p\">)</span>\n    email <span class=\"o\">=</span> models<span class=\"o\">.</span>EmailField<span class=\"p\">()</span>\n    headshot <span class=\"o\">=</span> models<span class=\"o\">.</span>ImageField<span class=\"p\">(</span>upload_to<span class=\"o\">=</span><span class=\"s2\">&quot;author_headshots&quot;</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span> <span class=\"fm\">__str__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span>name\n\n\n<span class=\"k\">class</span> <span class=\"nc\">Book</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    title <span class=\"o\">=</span> models<span class=\"o\">.</span>CharField<span class=\"p\">(</span>max_length<span class=\"o\">=</span><span class=\"mi\">100</span><span class=\"p\">)</span>\n    authors <span class=\"o\">=</span> models<span class=\"o\">.</span>ManyToManyField<span class=\"p\">(</span><span class=\"s2\">&quot;Author&quot;</span><span class=\"p\">)</span>\n    publisher <span class=\"o\">=</span> models<span class=\"o\">.</span>ForeignKey<span class=\"p\">(</span>Publisher<span class=\"p\">,</span> on_delete<span class=\"o\">=</span>models<span class=\"o\">.</span>CASCADE<span class=\"p\">)</span>\n    publication_date <span class=\"o\">=</span> models<span class=\"o\">.</span>DateField<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=\"c1\"># views.py</span>\n<span class=\"kn\">from</span> <span class=\"nn\">django.views.generic</span> <span class=\"kn\">import</span> ListView\n<span class=\"kn\">from</span> <span class=\"nn\">books.models</span> <span class=\"kn\">import</span> Publisher\n\n\n<span class=\"k\">class</span> <span class=\"nc\">PublisherListView</span><span class=\"p\">(</span>ListView<span class=\"p\">):</span>\n    model <span class=\"o\">=</span> Publisher\n</code></pre></div>\n<p>最後に、このビューを URL にフックさせます。</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\">books.views</span> <span class=\"kn\">import</span> PublisherListView\n\nurlpatterns <span class=\"o\">=</span> <span class=\"p\">[</span>\n    path<span class=\"p\">(</span><span class=\"s2\">&quot;publishers/&quot;</span><span class=\"p\">,</span> PublisherListView<span class=\"o\">.</span>as_view<span class=\"p\">()),</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>書く必要のある Python コードは、これですべてです。まだテンプレートを書く必要はありますけれど。ビューで使用するテンプレート名を <code class=\"docutils literal notranslate\">template_name</code> 属性に明示的に書くこともできますが、この属性を省略した場合でも、Django はオブジェクト名から推論してくれます。この場合は、テンプレート名は <code class=\"docutils literal notranslate\">&quot;books/publisher_list.html&quot;</code> になります。&quot;books&quot; の部分はモデルを定義したアプリの名前から来ていますが、&quot;publisher&quot; の部分はモデル名を小文字にした名前になっています。</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">注釈</p>\n<p>したがって、たとえば <a class=\"reference internal\" href=\"/ja/5.1/ref/settings/#std-setting-TEMPLATES\"><code class=\"xref std std-setting docutils literal notranslate\">TEMPLATES</code></a> 内で <code class=\"docutils literal notranslate\">DjangoTemplates</code> バックエンドの <code class=\"docutils literal notranslate\">APP_DIRS</code> オプションを True に設定した場合、テンプレートの場所は次のパスになります。/path/to/project/books/templates/books/publisher_list.html</p>\n</aside>\n<p>このテンプレートは、すべての publisher オブジェクトを含んだ <code class=\"docutils literal notranslate\">object_list</code> という変数を持つコンテキストとともにレンダリングされます。よって、テンプレートは次のように書けます。</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">extends</span> <span class=\"s2\">&quot;base.html&quot;</span> <span class=\"cp\">%}</span>\n\n<span class=\"cp\">{%</span> <span class=\"k\">block</span> <span class=\"nv\">content</span> <span class=\"cp\">%}</span>\n    <span class=\"p\">&lt;</span><span class=\"nt\">h2</span><span class=\"p\">&gt;</span>Publishers<span class=\"p\">&lt;/</span><span class=\"nt\">h2</span><span class=\"p\">&gt;</span>\n    <span class=\"p\">&lt;</span><span class=\"nt\">ul</span><span class=\"p\">&gt;</span>\n        <span class=\"cp\">{%</span> <span class=\"k\">for</span> <span class=\"nv\">publisher</span> <span class=\"k\">in</span> <span class=\"nv\">object_list</span> <span class=\"cp\">%}</span>\n            <span class=\"p\">&lt;</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">publisher.name</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>\n        <span class=\"cp\">{%</span> <span class=\"k\">endfor</span> <span class=\"cp\">%}</span>\n    <span class=\"p\">&lt;/</span><span class=\"nt\">ul</span><span class=\"p\">&gt;</span>\n<span class=\"cp\">{%</span> <span class=\"k\">endblock</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>ジェネリックビューの優れた機能はすべて、ジェネリックビューに設定された属性を変更することで得られます。この <a class=\"reference internal\" href=\"/ja/5.1/ref/class-based-views/\"><span class=\"doc\">ジェネリックビューのリファレンス</span></a> のドキュメントの残りの部分では、ジェネリックビューをカスタマイズしたり拡張したりする一般的な方法のいくつかを検討します。本当にそれだけです。</p>\n<section id=\"making-friendly-template-contexts\">\n<h3>「親切な」テンプレートコンテキストを作る<a class=\"heading-anchor\" href=\"#making-friendly-template-contexts\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>コード例の出版社をリストするテンプレートが、すべての出版社を <code class=\"docutils literal notranslate\">object_list</code> という名前の変数に格納していたことに気づいたかもしれません。これでもたしかに機能的には正しく動作しますが、テンプレートを書く人にとっては、とてもではありませんが「親切」とは言えません。ここではこの変数には出版社のリストが入っているのだと「事実として知らなければならない」わけです。</p>\n<p>実は、モデルオブジェクトを扱っている場合には、この問題はすでに対処されています。オブジェクトまたは queryset を扱う時、Django はモデルのクラス名を小文字にした名前を使ってコンテキストを設定できます。デフォルトの <code class=\"docutils literal notranslate\">object_list</code> エントリーに加えて、たとえば <code class=\"docutils literal notranslate\">publisher_list</code> のような変数に、全く同じデータが格納されているのです。</p>\n<p>しかし、この名前でも良くないと感じるなら、コンテキストの変数名を手動で設定することもできます。次のように、ジェネリックビューの <code class=\"docutils literal notranslate\">context_object_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=\"c1\"># views.py</span>\n<span class=\"kn\">from</span> <span class=\"nn\">django.views.generic</span> <span class=\"kn\">import</span> ListView\n<span class=\"kn\">from</span> <span class=\"nn\">books.models</span> <span class=\"kn\">import</span> Publisher\n\n\n<span class=\"k\">class</span> <span class=\"nc\">PublisherListView</span><span class=\"p\">(</span>ListView<span class=\"p\">):</span>\n    model <span class=\"o\">=</span> Publisher\n    context_object_name <span class=\"o\">=</span> <span class=\"s2\">&quot;my_favorite_publishers&quot;</span>\n</code></pre></div>\n<p>分かりやすい <code class=\"docutils literal notranslate\">context_object_name</code> を設定するのはいつでも良い考えです。テンプレートのデザイン担当の同僚に、きっと感謝されるでしょう。</p>\n</section>\n<section id=\"adding-extra-context\">\n<span id=\"id1\"></span><h3>追加のコンテキストを追加する<a class=\"heading-anchor\" href=\"#adding-extra-context\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>ジェネリックビューが提供する以外の追加情報が必要になることはよくあります。たとえば、各出版社の詳細ページで全書籍リストを表示したくなったとします。 <a class=\"reference internal\" href=\"/ja/5.1/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView\" title=\"django.views.generic.detail.DetailView\"><code class=\"xref py py-class docutils literal notranslate\">DetailView</code></a> ジェネリックビューは出版社をコンテキストに設定してくれますが、テンプレートに必要な他の追加情報を使うにはどうすれば良いのでしょうか？</p>\n<p>その答えは、 <a class=\"reference internal\" href=\"/ja/5.1/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView\" title=\"django.views.generic.detail.DetailView\"><code class=\"xref py py-class docutils literal notranslate\">DetailView</code></a> をサブクラス化して、 <code class=\"docutils literal notranslate\">get_context_data</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.views.generic</span> <span class=\"kn\">import</span> DetailView\n<span class=\"kn\">from</span> <span class=\"nn\">books.models</span> <span class=\"kn\">import</span> Book<span class=\"p\">,</span> Publisher\n\n\n<span class=\"k\">class</span> <span class=\"nc\">PublisherDetailView</span><span class=\"p\">(</span>DetailView<span class=\"p\">):</span>\n    model <span class=\"o\">=</span> Publisher\n\n    <span class=\"k\">def</span> <span class=\"nf\">get_context_data</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"o\">**</span>kwargs<span class=\"p\">):</span>\n        <span class=\"c1\"># Call the base implementation first to get a context</span>\n        context <span class=\"o\">=</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span>get_context_data<span class=\"p\">(</span><span class=\"o\">**</span>kwargs<span class=\"p\">)</span>\n        <span class=\"c1\"># Add in a QuerySet of all the books</span>\n        context<span class=\"p\">[</span><span class=\"s2\">&quot;book_list&quot;</span><span class=\"p\">]</span> <span class=\"o\">=</span> Book<span class=\"o\">.</span>objects<span class=\"o\">.</span>all<span class=\"p\">()</span>\n        <span class=\"k\">return</span> context\n</code></pre></div>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">注釈</p>\n<p>通常、 <code class=\"docutils literal notranslate\">get_context_data</code> はすべての親クラスのコンテキストデータを現在のクラスのコンテキストデータにマージします。コンテキストを変更したい自分のクラスでこの動作を維持するには、必ずスーパークラスで <code class=\"docutils literal notranslate\">get_context_data</code> を呼び出すようにしてください。2 つのクラスが同じキーを定義しようとしない場合、これは期待通りの結果をもたらします。しかし、親クラスがキーを設定した後に (super を呼び出した後に) あるクラスがキーをオーバーライドしようとした場合、そのクラスの子クラスも親クラスを確実にオーバーライドしたいのであれば、super の後に明示的にキーを設定する必要があります。問題がある場合は、ビューのメソッドの解決順序を見直してみてください。</p>\n<p>もうひとつの考慮点は、クラスベースのジェネリックビューのコンテキストデータが コンテキストプロセッサによって提供されるデータを上書きしてしまうことです。たとえば、 <a class=\"reference internal\" href=\"/ja/5.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin.get_context_data\" title=\"django.views.generic.detail.SingleObjectMixin.get_context_data\"><code class=\"xref py py-meth docutils literal notranslate\">get_context_data()</code></a> を参照してください。</p>\n</aside>\n</section>\n<section id=\"viewing-subsets-of-objects\">\n<span id=\"generic-views-list-subsets\"></span><h3>オブジェクトのサブセットを表示する<a class=\"heading-anchor\" href=\"#viewing-subsets-of-objects\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>それでは次に、すべての場所で使っていた <code class=\"docutils literal notranslate\">model</code> 引数について詳しく見ていきましょう。<code class=\"docutils literal notranslate\">model</code> 引数は、ビューの操作対象となるデータベースのモデルを指定します。この引数は、1オブジェクトまたは複数オブジェクトを操作するすべてのジェネリックビューで使用可能です。しかし、<code class=\"docutils literal notranslate\">model</code> 引数は操作対象のオブジェクトを指定する唯一の方法ではありません。次のように、<code class=\"docutils literal notranslate\">queryset</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.views.generic</span> <span class=\"kn\">import</span> DetailView\n<span class=\"kn\">from</span> <span class=\"nn\">books.models</span> <span class=\"kn\">import</span> Publisher\n\n\n<span class=\"k\">class</span> <span class=\"nc\">PublisherDetailView</span><span class=\"p\">(</span>DetailView<span class=\"p\">):</span>\n    context_object_name <span class=\"o\">=</span> <span class=\"s2\">&quot;publisher&quot;</span>\n    queryset <span class=\"o\">=</span> Publisher<span class=\"o\">.</span>objects<span class=\"o\">.</span>all<span class=\"p\">()</span>\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\">model = Publisher</code> を指定することは、<code class=\"docutils literal notranslate\">queryset = Publisher.objects.all()</code> と言うのと同じことです。しかし、<code class=\"docutils literal notranslate\">queryset</code> を使用してオブジェクトのフィルタリングされたリストを定義することで、ビューで表示されるオブジェクトについてより具体的にすることができます（<a class=\"reference internal\" href=\"/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet\" title=\"django.db.models.query.QuerySet\"><code class=\"xref py py-class docutils literal notranslate\">QuerySet</code></a> オブジェクトについての詳細は <a class=\"reference internal\" href=\"/ja/5.1/topics/db/queries/\"><span class=\"doc\">クエリを作成する</span></a> を参照し、完全な詳細については <a class=\"reference internal\" href=\"/ja/5.1/ref/class-based-views/\"><span class=\"doc\">クラスベースのビューのリファレンス</span></a> を参照してください）。</p>\n<p>例として、本を出版日で新しい順に並び替えたくなったとしたら、次のように書けます。</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.views.generic</span> <span class=\"kn\">import</span> ListView\n<span class=\"kn\">from</span> <span class=\"nn\">books.models</span> <span class=\"kn\">import</span> Book\n\n\n<span class=\"k\">class</span> <span class=\"nc\">BookListView</span><span class=\"p\">(</span>ListView<span class=\"p\">):</span>\n    queryset <span class=\"o\">=</span> Book<span class=\"o\">.</span>objects<span class=\"o\">.</span>order_by<span class=\"p\">(</span><span class=\"s2\">&quot;-publication_date&quot;</span><span class=\"p\">)</span>\n    context_object_name <span class=\"o\">=</span> <span class=\"s2\">&quot;book_list&quot;</span>\n</code></pre></div>\n<p>これは小さな例ですが、queryset の概念は上手く表現できていると思います。普通はただ並び替える以上のことをすることになるでしょう。特定の出版社の書籍リストを表示したい場合にも、同じテクニックが使えます。</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.generic</span> <span class=\"kn\">import</span> ListView\n<span class=\"kn\">from</span> <span class=\"nn\">books.models</span> <span class=\"kn\">import</span> Book\n\n\n<span class=\"k\">class</span> <span class=\"nc\">AcmeBookListView</span><span class=\"p\">(</span>ListView<span class=\"p\">):</span>\n    context_object_name <span class=\"o\">=</span> <span class=\"s2\">&quot;book_list&quot;</span>\n    queryset <span class=\"o\">=</span> Book<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>publisher__name<span class=\"o\">=</span><span class=\"s2\">&quot;ACME Publishing&quot;</span><span class=\"p\">)</span>\n    template_name <span class=\"o\">=</span> <span class=\"s2\">&quot;books/acme_list.html&quot;</span>\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\">queryset</code> がフィルタリングされただけではなく、テンプレート名も変更されているのがわかります。そうしないと、ジェネリックビューは「素の」オブジェクトリストと同じテンプレートを使ってしまいます。しかし、それは意図したものではないはずです。</p>\n<p>同時に注意しておきたいのは、この方法は特定の出版社の本をリストアップするにはあまりエレガントな方法ではないということです。新しく出版社のページを追加する必要が生じるたびにURLconf に数行を追加する必要があるので、これでは数社以上追加するとなるとすでに無理があると分かるでしょう。この問題の解決策は、次のセクションで議論します。</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">注釈</p>\n<p><code class=\"docutils literal notranslate\">/books/acme</code> のリクエスト時に 404 が表示された場合は、本当に 'ACME Publishing' という名前を持つ Publisher が存在しているか確認してください。このようなケースのためにジェネリックビューには <code class=\"docutils literal notranslate\">allow_empty</code> 引数というものもあります。詳しくは <a class=\"reference internal\" href=\"/ja/5.1/ref/class-based-views/\"><span class=\"doc\">クラスベースビューのリファレンス</span></a> を参照してください。</p>\n</aside>\n</section>\n<section id=\"dynamic-filtering\">\n<h3>動的なフィルタリング<a class=\"heading-anchor\" href=\"#dynamic-filtering\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>もう一つのよくあるニーズは、リストページの URL に指定した何らかのキーを使って、表示するオブジェクトをフィルタリングすることです。上の例では、出版社名を URLconf にハードコーディングしてしまっていましたが、もし任意の出版社に対するすべての書籍を表示するようなビューを書きたい場合には、どうすればいいでしょうか？</p>\n<p>便利なことに、 <code class=\"docutils literal notranslate\">ListView</code> にはオーバーライドできる <a class=\"reference internal\" href=\"/ja/5.1/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin.get_queryset\" title=\"django.views.generic.list.MultipleObjectMixin.get_queryset\"><code class=\"xref py py-meth docutils literal notranslate\">get_queryset()</code></a> メソッドがあります。デフォルトでは、 <code class=\"docutils literal notranslate\">queryset</code> 属性の値を返しますが、これを使用してロジックを追加できます。</p>\n<p>この機能がうまく動作するキーポイントは、クラスベースのビューが呼ばれる段階で <code class=\"docutils literal notranslate\">self</code> 内には様々な便利な値が格納されていることです。request (<code class=\"docutils literal notranslate\">self.request</code>)、位置引数 (<code class=\"docutils literal notranslate\">self.args</code>)、そして、キーワード引数 (<code class=\"docutils literal notranslate\">self.kwargs</code>) が、URLconf からキャプチャされてきています。</p>\n<p>ここでは、次のように URLconf に1つのキャプチャグループがあるとしましょう。</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\">books.views</span> <span class=\"kn\">import</span> PublisherBookListView\n\nurlpatterns <span class=\"o\">=</span> <span class=\"p\">[</span>\n    path<span class=\"p\">(</span><span class=\"s2\">&quot;books/&lt;publisher&gt;/&quot;</span><span class=\"p\">,</span> PublisherBookListView<span class=\"o\">.</span>as_view<span class=\"p\">()),</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>次に、<code class=\"docutils literal notranslate\">PublisherBookListView</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=\"c1\"># views.py</span>\n<span class=\"kn\">from</span> <span class=\"nn\">django.shortcuts</span> <span class=\"kn\">import</span> get_object_or_404\n<span class=\"kn\">from</span> <span class=\"nn\">django.views.generic</span> <span class=\"kn\">import</span> ListView\n<span class=\"kn\">from</span> <span class=\"nn\">books.models</span> <span class=\"kn\">import</span> Book<span class=\"p\">,</span> Publisher\n\n\n<span class=\"k\">class</span> <span class=\"nc\">PublisherBookListView</span><span class=\"p\">(</span>ListView<span class=\"p\">):</span>\n    template_name <span class=\"o\">=</span> <span class=\"s2\">&quot;books/books_by_publisher.html&quot;</span>\n\n    <span class=\"k\">def</span> <span class=\"nf\">get_queryset</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span>publisher <span class=\"o\">=</span> get_object_or_404<span class=\"p\">(</span>Publisher<span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"bp\">self</span><span class=\"o\">.</span>kwargs<span class=\"p\">[</span><span class=\"s2\">&quot;publisher&quot;</span><span class=\"p\">])</span>\n        <span class=\"k\">return</span> Book<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>publisher<span class=\"o\">=</span><span class=\"bp\">self</span><span class=\"o\">.</span>publisher<span class=\"p\">)</span>\n</code></pre></div>\n<p>queryset の選択に追加のロジックを加えるために <code class=\"docutils literal notranslate\">get_queryset</code> を使うテクニックは、便利で強力です。望むなら、たとえば <code class=\"docutils literal notranslate\">self.request.user</code> で現在のユーザーの情報でフィルタリングしたり、もっと複雑なロジックを追加したりすることも可能です。</p>\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=\"c1\"># ...</span>\n\n\n<span class=\"k\">def</span> <span class=\"nf\">get_context_data</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"o\">**</span>kwargs<span class=\"p\">):</span>\n    <span class=\"c1\"># Call the base implementation first to get a context</span>\n    context <span class=\"o\">=</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span>get_context_data<span class=\"p\">(</span><span class=\"o\">**</span>kwargs<span class=\"p\">)</span>\n    <span class=\"c1\"># Add in the publisher</span>\n    context<span class=\"p\">[</span><span class=\"s2\">&quot;publisher&quot;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span>publisher\n    <span class=\"k\">return</span> context\n</code></pre></div>\n</section>\n<section id=\"performing-extra-work\">\n<span id=\"generic-views-extra-work\"></span><h3>追加の処理を実行する<a class=\"heading-anchor\" href=\"#performing-extra-work\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>最後に見る共通パターンは、ジェネリックビューの呼び出しの前後で追加の処理を実行するというものです。</p>\n<p><code class=\"docutils literal notranslate\">Author</code> モデルに <code class=\"docutils literal notranslate\">last_accessed</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=\"c1\"># models.py</span>\n<span class=\"kn\">from</span> <span class=\"nn\">django.db</span> <span class=\"kn\">import</span> models\n\n\n<span class=\"k\">class</span> <span class=\"nc\">Author</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    salutation <span class=\"o\">=</span> models<span class=\"o\">.</span>CharField<span class=\"p\">(</span>max_length<span class=\"o\">=</span><span class=\"mi\">10</span><span class=\"p\">)</span>\n    name <span class=\"o\">=</span> models<span class=\"o\">.</span>CharField<span class=\"p\">(</span>max_length<span class=\"o\">=</span><span class=\"mi\">200</span><span class=\"p\">)</span>\n    email <span class=\"o\">=</span> models<span class=\"o\">.</span>EmailField<span class=\"p\">()</span>\n    headshot <span class=\"o\">=</span> models<span class=\"o\">.</span>ImageField<span class=\"p\">(</span>upload_to<span class=\"o\">=</span><span class=\"s2\">&quot;author_headshots&quot;</span><span class=\"p\">)</span>\n    last_accessed <span class=\"o\">=</span> models<span class=\"o\">.</span>DateTimeField<span class=\"p\">()</span>\n</code></pre></div>\n<p>汎用の <code class=\"docutils literal notranslate\">DetailView</code> クラスはこのフィールドについて何も知りませんが、このフィールドを最新の状態に保つためのカスタムビューをもう一度作成できます。</p>\n<p>まず、著者の詳細ビューを追加して、URLconf にカスタムビューを使うようにする必要があります。</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.urls</span> <span class=\"kn\">import</span> path\n<span class=\"kn\">from</span> <span class=\"nn\">books.views</span> <span class=\"kn\">import</span> AuthorDetailView\n\nurlpatterns <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"c1\"># ...</span>\n    path<span class=\"p\">(</span><span class=\"s2\">&quot;authors/&lt;int:pk&gt;/&quot;</span><span class=\"p\">,</span> AuthorDetailView<span class=\"o\">.</span>as_view<span class=\"p\">(),</span> name<span class=\"o\">=</span><span class=\"s2\">&quot;author-detail&quot;</span><span class=\"p\">),</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>次に、新しいビューを記述します（ <code class=\"docutils literal notranslate\">get_object</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.utils</span> <span class=\"kn\">import</span> timezone\n<span class=\"kn\">from</span> <span class=\"nn\">django.views.generic</span> <span class=\"kn\">import</span> DetailView\n<span class=\"kn\">from</span> <span class=\"nn\">books.models</span> <span class=\"kn\">import</span> Author\n\n\n<span class=\"k\">class</span> <span class=\"nc\">AuthorDetailView</span><span class=\"p\">(</span>DetailView<span class=\"p\">):</span>\n    queryset <span class=\"o\">=</span> Author<span class=\"o\">.</span>objects<span class=\"o\">.</span>all<span class=\"p\">()</span>\n\n    <span class=\"k\">def</span> <span class=\"nf\">get_object</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        obj <span class=\"o\">=</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span>get_object<span class=\"p\">()</span>\n        <span class=\"c1\"># Record the last accessed date</span>\n        obj<span class=\"o\">.</span>last_accessed <span class=\"o\">=</span> timezone<span class=\"o\">.</span>now<span class=\"p\">()</span>\n        obj<span class=\"o\">.</span>save<span class=\"p\">()</span>\n        <span class=\"k\">return</span> obj\n</code></pre></div>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">注釈</p>\n<p>ここで URLconf は <code class=\"docutils literal notranslate\">pk</code> という名前のキャプチャグループを使っています。この名前は <code class=\"docutils literal notranslate\">DetailView</code> が queryset をフィルタするのに使うプライマリキーの値を見付けるためのデフォルトの名前です。</p>\n<p>グループを別の名前で呼び出したい場合は、ビューに <a class=\"reference internal\" href=\"/ja/5.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin.pk_url_kwarg\" title=\"django.views.generic.detail.SingleObjectMixin.pk_url_kwarg\"><code class=\"xref py py-attr docutils literal notranslate\">pk_url_kwarg</code></a> を指定します。</p>\n</aside>\n</section>\n</section>","rootId":"built-in-class-based-generic-views","toc":[{"title":"ジェネリックビューを拡張する","anchor":"extending-generic-views","children":[]},{"title":"オブジェクトのジェネリックビュー","anchor":"generic-views-of-objects","children":[{"title":"「親切な」テンプレートコンテキストを作る","anchor":"making-friendly-template-contexts","children":[]},{"title":"追加のコンテキストを追加する","anchor":"adding-extra-context","children":[]},{"title":"オブジェクトのサブセットを表示する","anchor":"viewing-subsets-of-objects","children":[]},{"title":"動的なフィルタリング","anchor":"dynamic-filtering","children":[]},{"title":"追加の処理を実行する","anchor":"performing-extra-work","children":[]}]}],"breadcrumbs":[{"docname":"topics/index","title":"Django を使う","url":"/ja/5.1/topics/"},{"docname":"topics/class-based-views/index","title":"クラスベースビュー","url":"/ja/5.1/topics/class-based-views/"}],"prev":{"docname":"topics/class-based-views/intro","title":"クラスベースビュー入門","url":"/ja/5.1/topics/class-based-views/intro/"},"next":{"docname":"topics/class-based-views/generic-editing","title":"クラスベースのビューでフォームを扱う","url":"/ja/5.1/topics/class-based-views/generic-editing/"},"formats":{"html":"/ja/5.1/topics/class-based-views/generic-display/","markdown":"/ja/5.1/topics/class-based-views/generic-display.md","json":"/ja/5.1/topics/class-based-views/generic-display.json"},"source":"https://github.com/django/django/blob/stable/5.1.x/docs/topics/class-based-views/generic-display.txt","official":"https://docs.djangoproject.com/ja/5.1/topics/class-based-views/generic-display/","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"]}