{"title":"Built-in class-based generic views","version":"6.1","locale":"el","docname":"topics/class-based-views/generic-display","url":"/el/6.1/topics/class-based-views/generic-display/","canonical":"https://djangodocs.dev/el/6.1/topics/class-based-views/generic-display/","summary":"Writing web applications can be monotonous, because we repeat certain patterns again and again.","html":"<h1>Built-in class-based generic views<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>Writing web applications can be monotonous, because we repeat certain patterns\nagain and again. Django tries to take away some of that monotony at the model\nand template layers, but web developers also experience this boredom at the\nview level.</p>\n<p>Django’s <em>generic views</em> were developed to ease that pain. They take certain\ncommon idioms and patterns found in view development and abstract them so that\nyou can quickly write common views of data without having to write too much\ncode.</p>\n<p>We can recognize certain common tasks, like displaying a list of objects, and\nwrite code that displays a list of <em>any</em> object. Then the model in question can\nbe passed as an extra argument to the URLconf.</p>\n<p>Django ships with generic views to do the following:</p>\n<ul class=\"simple\">\n<li><p>Display list and detail pages for a single object. If we were creating an\napplication to manage conferences then a <code class=\"docutils literal notranslate\">TalkListView</code> and a\n<code class=\"docutils literal notranslate\">RegisteredUserListView</code> would be examples of list views. A single\ntalk page is an example of what we call a «detail» view.</p></li>\n<li><p>Present date-based objects in year/month/day archive pages,\nassociated detail, and «latest» pages.</p></li>\n<li><p>Allow users to create, update, and delete objects – with or\nwithout authorization.</p></li>\n</ul>\n<p>Taken together, these views provide interfaces to perform the most common tasks\ndevelopers encounter.</p>\n<section id=\"extending-generic-views\">\n<h2>Extending generic views<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>There’s no question that using generic views can speed up development\nsubstantially. In most projects, however, there comes a moment when the\ngeneric views no longer suffice. Indeed, the most common question asked by new\nDjango developers is how to make generic views handle a wider array of\nsituations.</p>\n<p>This is one of the reasons generic views were redesigned for the 1.3 release -\npreviously, they were view functions with a bewildering array of options; now,\nrather than passing in a large amount of configuration in the URLconf, the\nrecommended way to extend generic views is to subclass them, and override their\nattributes or methods.</p>\n<p>That said, generic views will have a limit. If you find you’re struggling to\nimplement your view as a subclass of a generic view, then you may find it more\neffective to write just the code you need, using your own class-based or\nfunctional views.</p>\n<p>More examples of generic views are available in some third party applications,\nor you could write your own as needed.</p>\n</section>\n<section id=\"generic-views-of-objects\">\n<h2>Generic views of objects<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=\"/el/6.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> certainly is useful, but\nDjango’s generic views really shine when it comes to presenting views of your\ndatabase content. Because it’s such a common task, Django comes with a handful\nof built-in generic views to help generate list and detail views of objects.</p>\n<p>Let’s start by looking at some examples of showing a list of objects or an\nindividual object.</p>\n<p>We’ll be using these models:</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>Now we need to define a 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=\"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>Finally hook that view into your urls:</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>That’s all the Python code we need to write. We still need to write a template,\nhowever. We could explicitly tell the view which template to use by adding a\n<code class=\"docutils literal notranslate\">template_name</code> attribute to the view, but in the absence of an explicit\ntemplate Django will infer one from the object’s name. In this case, the\ninferred template will be <code class=\"docutils literal notranslate\">&quot;books/publisher_list.html&quot;</code> – the «books» part\ncomes from the name of the app that defines the model, while the «publisher»\nbit is the lowercased version of the model’s name.</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Σημείωση</p>\n<p>Thus, when (for example) the <code class=\"docutils literal notranslate\">APP_DIRS</code> option of a <code class=\"docutils literal notranslate\">DjangoTemplates</code>\nbackend is set to True in <a class=\"reference internal\" href=\"/el/6.1/ref/settings/#std-setting-TEMPLATES\"><code class=\"xref std std-setting docutils literal notranslate\">TEMPLATES</code></a>, a template location could\nbe: /path/to/project/books/templates/books/publisher_list.html</p>\n</aside>\n<p>This template will be rendered against a context containing a variable called\n<code class=\"docutils literal notranslate\">object_list</code> that contains all the publisher objects. A template might look\nlike this:</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>That’s really all there is to it. All the cool features of generic views come\nfrom changing the attributes set on the generic view. The\n<a class=\"reference internal\" href=\"/el/6.1/ref/class-based-views/\"><span class=\"doc\">generic views reference</span></a> documents all the\ngeneric views and their options in detail; the rest of this document will\nconsider some of the common ways you might customize and extend generic views.</p>\n<section id=\"making-friendly-template-contexts\">\n<h3>Making «friendly» template contexts<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>You might have noticed that our sample publisher list template stores all the\npublishers in a variable named <code class=\"docutils literal notranslate\">object_list</code>. While this works just fine, it\nisn’t all that «friendly» to template authors: they have to «just know» that\nthey’re dealing with publishers here.</p>\n<p>Well, if you’re dealing with a model object, this is already done for you. When\nyou are dealing with an object or queryset, Django is able to populate the\ncontext using the lowercased version of the model class” name. This is provided\nin addition to the default <code class=\"docutils literal notranslate\">object_list</code> entry, but contains exactly the same\ndata, i.e. <code class=\"docutils literal notranslate\">publisher_list</code>.</p>\n<p>If this still isn’t a good match, you can manually set the name of the\ncontext variable. The <code class=\"docutils literal notranslate\">context_object_name</code> attribute on a generic view\nspecifies the context variable to use:</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>Providing a useful <code class=\"docutils literal notranslate\">context_object_name</code> is always a good idea. Your\ncoworkers who design templates will thank you.</p>\n</section>\n<section id=\"adding-extra-context\">\n<span id=\"id1\"></span><h3>Adding extra context<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>Often you need to present some extra information beyond that provided by the\ngeneric view. For example, think of showing a list of all the books on each\npublisher detail page. The <a class=\"reference internal\" href=\"/el/6.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>\ngeneric view provides the publisher to the context, but how do we get\nadditional information in that template?</p>\n<p>The answer is to subclass <a class=\"reference internal\" href=\"/el/6.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>\nand provide your own implementation of the <code class=\"docutils literal notranslate\">get_context_data</code> method.\nThe default implementation adds the object being displayed to the template, but\nyou can override it to send more:</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>Generally, <code class=\"docutils literal notranslate\">get_context_data</code> will merge the context data of all parent\nclasses with those of the current class. To preserve this behavior in your\nown classes where you want to alter the context, you should be sure to call\n<code class=\"docutils literal notranslate\">get_context_data</code> on the super class. When no two classes try to define\nthe same key, this will give the expected results. However if any class\nattempts to override a key after parent classes have set it (after the call\nto super), any children of that class will also need to explicitly set it\nafter super if they want to be sure to override all parents. If you’re\nhaving trouble, review the method resolution order of your view.</p>\n<p>Another consideration is that the context data from class-based generic\nviews will override data provided by context processors; see\n<a class=\"reference internal\" href=\"/el/6.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> for\nan example.</p>\n</aside>\n</section>\n<section id=\"viewing-subsets-of-objects\">\n<span id=\"generic-views-list-subsets\"></span><h3>Viewing subsets of objects<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>Now let’s take a closer look at the <code class=\"docutils literal notranslate\">model</code> argument we’ve been\nusing all along. The <code class=\"docutils literal notranslate\">model</code> argument, which specifies the database\nmodel that the view will operate upon, is available on all the\ngeneric views that operate on a single object or a collection of\nobjects. However, the <code class=\"docutils literal notranslate\">model</code> argument is not the only way to\nspecify the objects that the view will operate upon – you can also\nspecify the list of objects using the <code class=\"docutils literal notranslate\">queryset</code> argument:</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>Specifying <code class=\"docutils literal notranslate\">model = Publisher</code> is shorthand for saying <code class=\"docutils literal notranslate\">queryset =\nPublisher.objects.all()</code>. However, by using <code class=\"docutils literal notranslate\">queryset</code> to define a filtered\nlist of objects you can be more specific about the objects that will be visible\nin the view (see <a class=\"reference internal\" href=\"/el/6.1/topics/db/queries/\"><span class=\"doc\">Making queries</span></a> for more information about\n<a class=\"reference internal\" href=\"/el/6.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> objects, and see the\n<a class=\"reference internal\" href=\"/el/6.1/ref/class-based-views/\"><span class=\"doc\">class-based views reference</span></a> for the\ncomplete details).</p>\n<p>To pick an example, we might want to order a list of books by publication date,\nwith the most recent first:</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>That’s a pretty minimal example, but it illustrates the idea nicely. You’ll\nusually want to do more than just reorder objects. If you want to present a\nlist of books by a particular publisher, you can use the same technique:</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>Notice that along with a filtered <code class=\"docutils literal notranslate\">queryset</code>, we’re also using a custom\ntemplate name. If we didn’t, the generic view would use the same template as\nthe «vanilla» object list, which might not be what we want.</p>\n<p>Also notice that this isn’t a very elegant way of doing publisher-specific\nbooks. If we want to add another publisher page, we’d need another handful of\nlines in the URLconf, and more than a few publishers would get unreasonable.\nWe’ll deal with this problem in the next section.</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Σημείωση</p>\n<p>If you get a 404 when requesting <code class=\"docutils literal notranslate\">/books/acme/</code>, check to ensure you\nactually have a Publisher with the name “ACME Publishing”. Generic\nviews have an <code class=\"docutils literal notranslate\">allow_empty</code> parameter for this case. See the\n<a class=\"reference internal\" href=\"/el/6.1/ref/class-based-views/\"><span class=\"doc\">class-based-views reference</span></a> for more\ndetails.</p>\n</aside>\n</section>\n<section id=\"dynamic-filtering\">\n<h3>Dynamic filtering<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>Another common need is to filter down the objects given in a list page by some\nkey in the URL. Earlier we hardcoded the publisher’s name in the URLconf, but\nwhat if we wanted to write a view that displayed all the books by some\narbitrary publisher?</p>\n<p>Handily, the <code class=\"docutils literal notranslate\">ListView</code> has a\n<a class=\"reference internal\" href=\"/el/6.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> method we\ncan override. By default, it returns the value of the <code class=\"docutils literal notranslate\">queryset</code> attribute,\nbut we can use it to add more logic.</p>\n<p>The key part to making this work is that when class-based views are called,\nvarious useful things are stored on <code class=\"docutils literal notranslate\">self</code>; as well as the request\n(<code class=\"docutils literal notranslate\">self.request</code>) this includes the positional (<code class=\"docutils literal notranslate\">self.args</code>) and name-based\n(<code class=\"docutils literal notranslate\">self.kwargs</code>) arguments captured according to the URLconf.</p>\n<p>Here, we have a URLconf with a single captured group:</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>Next, we’ll write the <code class=\"docutils literal notranslate\">PublisherBookListView</code> view itself:</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>Using <code class=\"docutils literal notranslate\">get_queryset</code> to add logic to the queryset selection is as convenient\nas it is powerful. For instance, if we wanted, we could use\n<code class=\"docutils literal notranslate\">self.request.user</code> to filter using the current user, or other more complex\nlogic.</p>\n<p>We can also add the publisher into the context at the same time, so we can\nuse it in the template:</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>Performing extra work<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>The last common pattern we’ll look at involves doing some extra work before\nor after calling the generic view.</p>\n<p>Imagine we had a <code class=\"docutils literal notranslate\">last_accessed</code> field on our <code class=\"docutils literal notranslate\">Author</code> model that we were\nusing to keep track of the last time anybody looked at that author:</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>The generic <code class=\"docutils literal notranslate\">DetailView</code> class wouldn’t know anything about this field, but\nonce again we could write a custom view to keep that field updated.</p>\n<p>First, we’d need to add an author detail bit in the URLconf to point to a\ncustom 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.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>Then we’d write our new view – <code class=\"docutils literal notranslate\">get_object</code> is the method that retrieves the\nobject – so we override it and wrap the call:</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>The URLconf here uses the named group <code class=\"docutils literal notranslate\">pk</code> - this name is the default\nname that <code class=\"docutils literal notranslate\">DetailView</code> uses to find the value of the primary key used to\nfilter the queryset.</p>\n<p>If you want to call the group something else, you can set\n<a class=\"reference internal\" href=\"/el/6.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>\non the view.</p>\n</aside>\n</section>\n</section>","rootId":"built-in-class-based-generic-views","toc":[{"title":"Extending generic views","anchor":"extending-generic-views","children":[]},{"title":"Generic views of objects","anchor":"generic-views-of-objects","children":[{"title":"Making «friendly» template contexts","anchor":"making-friendly-template-contexts","children":[]},{"title":"Adding extra context","anchor":"adding-extra-context","children":[]},{"title":"Viewing subsets of objects","anchor":"viewing-subsets-of-objects","children":[]},{"title":"Dynamic filtering","anchor":"dynamic-filtering","children":[]},{"title":"Performing extra work","anchor":"performing-extra-work","children":[]}]}],"breadcrumbs":[{"docname":"topics/index","title":"Using Django","url":"/el/6.1/topics/"},{"docname":"topics/class-based-views/index","title":"Class-based views","url":"/el/6.1/topics/class-based-views/"}],"prev":{"docname":"topics/class-based-views/intro","title":"Introduction to class-based views","url":"/el/6.1/topics/class-based-views/intro/"},"next":{"docname":"topics/class-based-views/generic-editing","title":"Form handling with class-based views","url":"/el/6.1/topics/class-based-views/generic-editing/"},"formats":{"html":"/el/6.1/topics/class-based-views/generic-display/","markdown":"/el/6.1/topics/class-based-views/generic-display.md","json":"/el/6.1/topics/class-based-views/generic-display.json"},"source":"https://github.com/django/django/blob/stable/6.1.x/docs/topics/class-based-views/generic-display.txt","official":"https://docs.djangoproject.com/el/6.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"],"inLocales":["en","sv","zh-hans","ga","fr","ja","id","it","pt-br","ko","es","el","pl"]}