Sophie

Sophie

distrib > Mageia > 6 > armv7hl > media > core-updates > by-pkgid > 65530c6176058f9b54858c3b4f6385e6 > files > 921

python-django-doc-1.8.19-1.mga6.noarch.rpm

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


<html xmlns="http://www.w3.org/1999/xhtml" lang="">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    
    <title>Built-in class-based generic views &#8212; Django 1.8.19 documentation</title>
    
    <link rel="stylesheet" href="../../_static/default.css" type="text/css" />
    <link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
    
    <script type="text/javascript">
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    '../../',
        VERSION:     '1.8.19',
        COLLAPSE_INDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  true
      };
    </script>
    <script type="text/javascript" src="../../_static/jquery.js"></script>
    <script type="text/javascript" src="../../_static/underscore.js"></script>
    <script type="text/javascript" src="../../_static/doctools.js"></script>
    <link rel="index" title="Index" href="../../genindex.html" />
    <link rel="search" title="Search" href="../../search.html" />
    <link rel="top" title="Django 1.8.19 documentation" href="../../contents.html" />
    <link rel="up" title="Class-based views" href="index.html" />
    <link rel="next" title="Form handling with class-based views" href="generic-editing.html" />
    <link rel="prev" title="Introduction to class-based views" href="intro.html" />



 
<script type="text/javascript" src="../../templatebuiltins.js"></script>
<script type="text/javascript">
(function($) {
    if (!django_template_builtins) {
       // templatebuiltins.js missing, do nothing.
       return;
    }
    $(document).ready(function() {
        // Hyperlink Django template tags and filters
        var base = "../../ref/templates/builtins.html";
        if (base == "#") {
            // Special case for builtins.html itself
            base = "";
        }
        // Tags are keywords, class '.k'
        $("div.highlight\\-html\\+django span.k").each(function(i, elem) {
             var tagname = $(elem).text();
             if ($.inArray(tagname, django_template_builtins.ttags) != -1) {
                 var fragment = tagname.replace(/_/, '-');
                 $(elem).html("<a href='" + base + "#" + fragment + "'>" + tagname + "</a>");
             }
        });
        // Filters are functions, class '.nf'
        $("div.highlight\\-html\\+django span.nf").each(function(i, elem) {
             var filtername = $(elem).text();
             if ($.inArray(filtername, django_template_builtins.tfilters) != -1) {
                 var fragment = filtername.replace(/_/, '-');
                 $(elem).html("<a href='" + base + "#" + fragment + "'>" + filtername + "</a>");
             }
        });
    });
})(jQuery);
</script>


  </head>
  <body role="document">

    <div class="document">
  <div id="custom-doc" class="yui-t6">
    <div id="hd">
      <h1><a href="../../index.html">Django 1.8.19 documentation</a></h1>
      <div id="global-nav">
        <a title="Home page" href="../../index.html">Home</a>  |
        <a title="Table of contents" href="../../contents.html">Table of contents</a>  |
        <a title="Global index" href="../../genindex.html">Index</a>  |
        <a title="Module index" href="../../py-modindex.html">Modules</a>
      </div>
      <div class="nav">
    &laquo; <a href="intro.html" title="Introduction to class-based views">previous</a>
     |
    <a href="../index.html" title="Using Django" accesskey="U">up</a>
   |
    <a href="generic-editing.html" title="Form handling with class-based views">next</a> &raquo;</div>
    </div>

    <div id="bd">
      <div id="yui-main">
        <div class="yui-b">
          <div class="yui-g" id="topics-class-based-views-generic-display">
            
  <div class="section" id="s-built-in-class-based-generic-views">
<span id="s-generic-views"></span><span id="built-in-class-based-generic-views"></span><span id="generic-views"></span><h1>Built-in class-based generic views<a class="headerlink" href="#built-in-class-based-generic-views" title="Permalink to this headline">¶</a></h1>
<p>Writing Web applications can be monotonous, because we repeat certain patterns
again and again. Django tries to take away some of that monotony at the model
and template layers, but Web developers also experience this boredom at the view
level.</p>
<p>Django&#8217;s <em>generic views</em> were developed to ease that pain. They take certain
common idioms and patterns found in view development and abstract them so that
you can quickly write common views of data without having to write too much
code.</p>
<p>We can recognize certain common tasks, like displaying a list of objects, and
write code that displays a list of <em>any</em> object. Then the model in question can
be passed as an extra argument to the URLconf.</p>
<p>Django ships with generic views to do the following:</p>
<ul class="simple">
<li>Display list and detail pages for a single object. If we were creating an
application to manage conferences then a <code class="docutils literal"><span class="pre">TalkListView</span></code> and a
<code class="docutils literal"><span class="pre">RegisteredUserListView</span></code> would be examples of list views. A single
talk page is an example of what we call a &#8220;detail&#8221; view.</li>
<li>Present date-based objects in year/month/day archive pages,
associated detail, and &#8220;latest&#8221; pages.</li>
<li>Allow users to create, update, and delete objects &#8211; with or
without authorization.</li>
</ul>
<p>Taken together, these views provide easy interfaces to perform the most common
tasks developers encounter.</p>
<div class="section" id="s-extending-generic-views">
<span id="extending-generic-views"></span><h2>Extending generic views<a class="headerlink" href="#extending-generic-views" title="Permalink to this headline">¶</a></h2>
<p>There&#8217;s no question that using generic views can speed up development
substantially. In most projects, however, there comes a moment when the
generic views no longer suffice. Indeed, the most common question asked by new
Django developers is how to make generic views handle a wider array of
situations.</p>
<p>This is one of the reasons generic views were redesigned for the 1.3 release -
previously, they were just view functions with a bewildering array of options;
now, rather than passing in a large amount of configuration in the URLconf,
the recommended way to extend generic views is to subclass them, and override
their attributes or methods.</p>
<p>That said, generic views will have a limit. If you find you&#8217;re struggling to
implement your view as a subclass of a generic view, then you may find it more
effective to write just the code you need, using your own class-based or
functional views.</p>
<p>More examples of generic views are available in some third party applications,
or you could write your own as needed.</p>
</div>
<div class="section" id="s-generic-views-of-objects">
<span id="generic-views-of-objects"></span><h2>Generic views of objects<a class="headerlink" href="#generic-views-of-objects" title="Permalink to this headline">¶</a></h2>
<p><a class="reference internal" href="../../ref/class-based-views/base.html#django.views.generic.base.TemplateView" title="django.views.generic.base.TemplateView"><code class="xref py py-class docutils literal"><span class="pre">TemplateView</span></code></a> certainly is useful, but
Django&#8217;s generic views really shine when it comes to presenting views of your
database content. Because it&#8217;s such a common task, Django comes with a handful
of built-in generic views that make generating list and detail views of objects
incredibly easy.</p>
<p>Let&#8217;s start by looking at some examples of showing a list of objects or an
individual object.</p>
<p>We&#8217;ll be using these models:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="c1"># models.py</span>
<span class="kn">from</span> <span class="nn">django.db</span> <span class="k">import</span> <span class="n">models</span>

<span class="k">class</span> <span class="nc">Publisher</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
    <span class="n">name</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">max_length</span><span class="o">=</span><span class="mi">30</span><span class="p">)</span>
    <span class="n">address</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">max_length</span><span class="o">=</span><span class="mi">50</span><span class="p">)</span>
    <span class="n">city</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">max_length</span><span class="o">=</span><span class="mi">60</span><span class="p">)</span>
    <span class="n">state_province</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">max_length</span><span class="o">=</span><span class="mi">30</span><span class="p">)</span>
    <span class="n">country</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">max_length</span><span class="o">=</span><span class="mi">50</span><span class="p">)</span>
    <span class="n">website</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">URLField</span><span class="p">()</span>

    <span class="k">class</span> <span class="nc">Meta</span><span class="p">:</span>
        <span class="n">ordering</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;-name&quot;</span><span class="p">]</span>

    <span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>              <span class="c1"># __unicode__ on Python 2</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span>

<span class="k">class</span> <span class="nc">Author</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
    <span class="n">salutation</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">max_length</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span>
    <span class="n">name</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">max_length</span><span class="o">=</span><span class="mi">200</span><span class="p">)</span>
    <span class="n">email</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">EmailField</span><span class="p">()</span>
    <span class="n">headshot</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">ImageField</span><span class="p">(</span><span class="n">upload_to</span><span class="o">=</span><span class="s1">&#39;author_headshots&#39;</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>              <span class="c1"># __unicode__ on Python 2</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span>

<span class="k">class</span> <span class="nc">Book</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
    <span class="n">title</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">max_length</span><span class="o">=</span><span class="mi">100</span><span class="p">)</span>
    <span class="n">authors</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">ManyToManyField</span><span class="p">(</span><span class="s1">&#39;Author&#39;</span><span class="p">)</span>
    <span class="n">publisher</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">ForeignKey</span><span class="p">(</span><span class="n">Publisher</span><span class="p">)</span>
    <span class="n">publication_date</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">DateField</span><span class="p">()</span>
</pre></div>
</div>
<p>Now we need to define a view:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="c1"># views.py</span>
<span class="kn">from</span> <span class="nn">django.views.generic</span> <span class="k">import</span> <span class="n">ListView</span>
<span class="kn">from</span> <span class="nn">books.models</span> <span class="k">import</span> <span class="n">Publisher</span>

<span class="k">class</span> <span class="nc">PublisherList</span><span class="p">(</span><span class="n">ListView</span><span class="p">):</span>
    <span class="n">model</span> <span class="o">=</span> <span class="n">Publisher</span>
</pre></div>
</div>
<p>Finally hook that view into your urls:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="c1"># urls.py</span>
<span class="kn">from</span> <span class="nn">django.conf.urls</span> <span class="k">import</span> <span class="n">url</span>
<span class="kn">from</span> <span class="nn">books.views</span> <span class="k">import</span> <span class="n">PublisherList</span>

<span class="n">urlpatterns</span> <span class="o">=</span> <span class="p">[</span>
    <span class="n">url</span><span class="p">(</span><span class="s1">r&#39;^publishers/$&#39;</span><span class="p">,</span> <span class="n">PublisherList</span><span class="o">.</span><span class="n">as_view</span><span class="p">()),</span>
<span class="p">]</span>
</pre></div>
</div>
<p>That&#8217;s all the Python code we need to write. We still need to write a template,
however. We could explicitly tell the view which template to use by adding a
<code class="docutils literal"><span class="pre">template_name</span></code> attribute to the view, but in the absence of an explicit
template Django will infer one from the object&#8217;s name. In this case, the
inferred template will be <code class="docutils literal"><span class="pre">&quot;books/publisher_list.html&quot;</span></code> &#8211; the &#8220;books&#8221; part
comes from the name of the app that defines the model, while the &#8220;publisher&#8221;
bit is just the lowercased version of the model&#8217;s name.</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">Thus, when (for example) the <code class="docutils literal"><span class="pre">APP_DIRS</span></code> option of a <code class="docutils literal"><span class="pre">DjangoTemplates</span></code>
backend is set to True in <a class="reference internal" href="../../ref/settings.html#std:setting-TEMPLATES"><code class="xref std std-setting docutils literal"><span class="pre">TEMPLATES</span></code></a>, a template location could
be: /path/to/project/books/templates/books/publisher_list.html</p>
</div>
<p>This template will be rendered against a context containing a variable called
<code class="docutils literal"><span class="pre">object_list</span></code> that contains all the publisher objects. A very simple template
might look like the following:</p>
<div class="highlight-html+django"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">extends</span> <span class="s2">&quot;base.html&quot;</span> <span class="cp">%}</span>

<span class="cp">{%</span> <span class="k">block</span> <span class="nv">content</span> <span class="cp">%}</span>
    <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>
    <span class="p">&lt;</span><span class="nt">ul</span><span class="p">&gt;</span>
        <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>
            <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>
        <span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
    <span class="p">&lt;/</span><span class="nt">ul</span><span class="p">&gt;</span>
<span class="cp">{%</span> <span class="k">endblock</span> <span class="cp">%}</span>
</pre></div>
</div>
<p>That&#8217;s really all there is to it. All the cool features of generic views come
from changing the attributes set on the generic view. The
<a class="reference internal" href="../../ref/class-based-views/index.html"><span class="doc">generic views reference</span></a> documents all the
generic views and their options in detail; the rest of this document will
consider some of the common ways you might customize and extend generic views.</p>
<div class="section" id="s-making-friendly-template-contexts">
<span id="making-friendly-template-contexts"></span><h3>Making &#8220;friendly&#8221; template contexts<a class="headerlink" href="#making-friendly-template-contexts" title="Permalink to this headline">¶</a></h3>
<p>You might have noticed that our sample publisher list template stores all the
publishers in a variable named <code class="docutils literal"><span class="pre">object_list</span></code>. While this works just fine, it
isn&#8217;t all that &#8220;friendly&#8221; to template authors: they have to &#8220;just know&#8221; that
they&#8217;re dealing with publishers here.</p>
<p>Well, if you&#8217;re dealing with a model object, this is already done for you. When
you are dealing with an object or queryset, Django is able to populate the
context using the lower cased version of the model class&#8217; name. This is
provided in addition to the default <code class="docutils literal"><span class="pre">object_list</span></code> entry, but contains exactly
the same data, i.e. <code class="docutils literal"><span class="pre">publisher_list</span></code>.</p>
<p>If this still isn&#8217;t a good match, you can manually set the name of the
context variable. The <code class="docutils literal"><span class="pre">context_object_name</span></code> attribute on a generic view
specifies the context variable to use:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="c1"># views.py</span>
<span class="kn">from</span> <span class="nn">django.views.generic</span> <span class="k">import</span> <span class="n">ListView</span>
<span class="kn">from</span> <span class="nn">books.models</span> <span class="k">import</span> <span class="n">Publisher</span>

<span class="k">class</span> <span class="nc">PublisherList</span><span class="p">(</span><span class="n">ListView</span><span class="p">):</span>
    <span class="n">model</span> <span class="o">=</span> <span class="n">Publisher</span>
    <span class="n">context_object_name</span> <span class="o">=</span> <span class="s1">&#39;my_favorite_publishers&#39;</span>
</pre></div>
</div>
<p>Providing a useful <code class="docutils literal"><span class="pre">context_object_name</span></code> is always a good idea. Your
coworkers who design templates will thank you.</p>
</div>
<div class="section" id="s-adding-extra-context">
<span id="s-id1"></span><span id="adding-extra-context"></span><span id="id1"></span><h3>Adding extra context<a class="headerlink" href="#adding-extra-context" title="Permalink to this headline">¶</a></h3>
<p>Often you simply need to present some extra information beyond that
provided by the generic view. For example, think of showing a list of
all the books on each publisher detail page. The
<a class="reference internal" href="../../ref/class-based-views/generic-display.html#django.views.generic.detail.DetailView" title="django.views.generic.detail.DetailView"><code class="xref py py-class docutils literal"><span class="pre">DetailView</span></code></a> generic view provides
the publisher to the context, but how do we get additional information
in that template?</p>
<p>The answer is to subclass <a class="reference internal" href="../../ref/class-based-views/generic-display.html#django.views.generic.detail.DetailView" title="django.views.generic.detail.DetailView"><code class="xref py py-class docutils literal"><span class="pre">DetailView</span></code></a>
and provide your own implementation of the <code class="docutils literal"><span class="pre">get_context_data</span></code> method.
The default implementation simply adds the object being displayed to the
template, but you can override it to send more:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.views.generic</span> <span class="k">import</span> <span class="n">DetailView</span>
<span class="kn">from</span> <span class="nn">books.models</span> <span class="k">import</span> <span class="n">Publisher</span><span class="p">,</span> <span class="n">Book</span>

<span class="k">class</span> <span class="nc">PublisherDetail</span><span class="p">(</span><span class="n">DetailView</span><span class="p">):</span>

    <span class="n">model</span> <span class="o">=</span> <span class="n">Publisher</span>

    <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><span class="n">kwargs</span><span class="p">):</span>
        <span class="c1"># Call the base implementation first to get a context</span>
        <span class="n">context</span> <span class="o">=</span> <span class="nb">super</span><span class="p">(</span><span class="n">PublisherDetail</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">get_context_data</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
        <span class="c1"># Add in a QuerySet of all the books</span>
        <span class="n">context</span><span class="p">[</span><span class="s1">&#39;book_list&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">Book</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>
        <span class="k">return</span> <span class="n">context</span>
</pre></div>
</div>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p>Generally, <code class="docutils literal"><span class="pre">get_context_data</span></code> will merge the context data of all parent
classes with those of the current class. To preserve this behavior in your
own classes where you want to alter the context, you should be sure to call
<code class="docutils literal"><span class="pre">get_context_data</span></code> on the super class. When no two classes try to define the
same key, this will give the expected results. However if any class
attempts to override a key after parent classes have set it (after the call
to super), any children of that class will also need to explicitly set it
after super if they want to be sure to override all parents. If you&#8217;re
having trouble, review the method resolution order of your view.</p>
<p class="last">Another consideration is that the context data from class-based generic
views will override data provided by context processors; see
<a class="reference internal" href="../../ref/class-based-views/mixins-single-object.html#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"><span class="pre">get_context_data()</span></code></a> for
an example.</p>
</div>
</div>
<div class="section" id="s-viewing-subsets-of-objects">
<span id="s-generic-views-list-subsets"></span><span id="viewing-subsets-of-objects"></span><span id="generic-views-list-subsets"></span><h3>Viewing subsets of objects<a class="headerlink" href="#viewing-subsets-of-objects" title="Permalink to this headline">¶</a></h3>
<p>Now let&#8217;s take a closer look at the <code class="docutils literal"><span class="pre">model</span></code> argument we&#8217;ve been
using all along. The <code class="docutils literal"><span class="pre">model</span></code> argument, which specifies the database
model that the view will operate upon, is available on all the
generic views that operate on a single object or a collection of
objects. However, the <code class="docutils literal"><span class="pre">model</span></code> argument is not the only way to
specify the objects that the view will operate upon &#8211; you can also
specify the list of objects using the <code class="docutils literal"><span class="pre">queryset</span></code> argument:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.views.generic</span> <span class="k">import</span> <span class="n">DetailView</span>
<span class="kn">from</span> <span class="nn">books.models</span> <span class="k">import</span> <span class="n">Publisher</span>

<span class="k">class</span> <span class="nc">PublisherDetail</span><span class="p">(</span><span class="n">DetailView</span><span class="p">):</span>

    <span class="n">context_object_name</span> <span class="o">=</span> <span class="s1">&#39;publisher&#39;</span>
    <span class="n">queryset</span> <span class="o">=</span> <span class="n">Publisher</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>
</pre></div>
</div>
<p>Specifying <code class="docutils literal"><span class="pre">model</span> <span class="pre">=</span> <span class="pre">Publisher</span></code> is really just shorthand for saying
<code class="docutils literal"><span class="pre">queryset</span> <span class="pre">=</span> <span class="pre">Publisher.objects.all()</span></code>. However, by using <code class="docutils literal"><span class="pre">queryset</span></code>
to define a filtered list of objects you can be more specific about the
objects that will be visible in the view (see <a class="reference internal" href="../db/queries.html"><span class="doc">Making queries</span></a>
for more information about <a class="reference internal" href="../../ref/models/querysets.html#django.db.models.query.QuerySet" title="django.db.models.query.QuerySet"><code class="xref py py-class docutils literal"><span class="pre">QuerySet</span></code></a> objects,
and see the <a class="reference internal" href="../../ref/class-based-views/index.html"><span class="doc">class-based views reference</span></a>
for the complete details).</p>
<p>To pick a simple example, we might want to order a list of books by
publication date, with the most recent first:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.views.generic</span> <span class="k">import</span> <span class="n">ListView</span>
<span class="kn">from</span> <span class="nn">books.models</span> <span class="k">import</span> <span class="n">Book</span>

<span class="k">class</span> <span class="nc">BookList</span><span class="p">(</span><span class="n">ListView</span><span class="p">):</span>
    <span class="n">queryset</span> <span class="o">=</span> <span class="n">Book</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">order_by</span><span class="p">(</span><span class="s1">&#39;-publication_date&#39;</span><span class="p">)</span>
    <span class="n">context_object_name</span> <span class="o">=</span> <span class="s1">&#39;book_list&#39;</span>
</pre></div>
</div>
<p>That&#8217;s a pretty simple example, but it illustrates the idea nicely. Of course,
you&#8217;ll usually want to do more than just reorder objects. If you want to
present a list of books by a particular publisher, you can use the same
technique:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.views.generic</span> <span class="k">import</span> <span class="n">ListView</span>
<span class="kn">from</span> <span class="nn">books.models</span> <span class="k">import</span> <span class="n">Book</span>

<span class="k">class</span> <span class="nc">AcmeBookList</span><span class="p">(</span><span class="n">ListView</span><span class="p">):</span>

    <span class="n">context_object_name</span> <span class="o">=</span> <span class="s1">&#39;book_list&#39;</span>
    <span class="n">queryset</span> <span class="o">=</span> <span class="n">Book</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">publisher__name</span><span class="o">=</span><span class="s1">&#39;ACME Publishing&#39;</span><span class="p">)</span>
    <span class="n">template_name</span> <span class="o">=</span> <span class="s1">&#39;books/acme_list.html&#39;</span>
</pre></div>
</div>
<p>Notice that along with a filtered <code class="docutils literal"><span class="pre">queryset</span></code>, we&#8217;re also using a custom
template name. If we didn&#8217;t, the generic view would use the same template as the
&#8220;vanilla&#8221; object list, which might not be what we want.</p>
<p>Also notice that this isn&#8217;t a very elegant way of doing publisher-specific
books. If we want to add another publisher page, we&#8217;d need another handful of
lines in the URLconf, and more than a few publishers would get unreasonable.
We&#8217;ll deal with this problem in the next section.</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">If you get a 404 when requesting <code class="docutils literal"><span class="pre">/books/acme/</span></code>, check to ensure you
actually have a Publisher with the name &#8216;ACME Publishing&#8217;.  Generic
views have an <code class="docutils literal"><span class="pre">allow_empty</span></code> parameter for this case.  See the
<a class="reference internal" href="../../ref/class-based-views/index.html"><span class="doc">class-based-views reference</span></a> for more
details.</p>
</div>
</div>
<div class="section" id="s-dynamic-filtering">
<span id="dynamic-filtering"></span><h3>Dynamic filtering<a class="headerlink" href="#dynamic-filtering" title="Permalink to this headline">¶</a></h3>
<p>Another common need is to filter down the objects given in a list page by some
key in the URL. Earlier we hard-coded the publisher&#8217;s name in the URLconf, but
what if we wanted to write a view that displayed all the books by some arbitrary
publisher?</p>
<p>Handily, the <code class="docutils literal"><span class="pre">ListView</span></code> has a
<a class="reference internal" href="../../ref/class-based-views/mixins-multiple-object.html#django.views.generic.list.MultipleObjectMixin.get_queryset" title="django.views.generic.list.MultipleObjectMixin.get_queryset"><code class="xref py py-meth docutils literal"><span class="pre">get_queryset()</span></code></a> method we
can override. Previously, it has just been returning the value of the
<code class="docutils literal"><span class="pre">queryset</span></code> attribute, but now we can add more logic.</p>
<p>The key part to making this work is that when class-based views are called,
various useful things are stored on <code class="docutils literal"><span class="pre">self</span></code>; as well as the request
(<code class="docutils literal"><span class="pre">self.request</span></code>) this includes the positional (<code class="docutils literal"><span class="pre">self.args</span></code>) and name-based
(<code class="docutils literal"><span class="pre">self.kwargs</span></code>) arguments captured according to the URLconf.</p>
<p>Here, we have a URLconf with a single captured group:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="c1"># urls.py</span>
<span class="kn">from</span> <span class="nn">django.conf.urls</span> <span class="k">import</span> <span class="n">url</span>
<span class="kn">from</span> <span class="nn">books.views</span> <span class="k">import</span> <span class="n">PublisherBookList</span>

<span class="n">urlpatterns</span> <span class="o">=</span> <span class="p">[</span>
    <span class="n">url</span><span class="p">(</span><span class="s1">r&#39;^books/([\w-]+)/$&#39;</span><span class="p">,</span> <span class="n">PublisherBookList</span><span class="o">.</span><span class="n">as_view</span><span class="p">()),</span>
<span class="p">]</span>
</pre></div>
</div>
<p>Next, we&#8217;ll write the <code class="docutils literal"><span class="pre">PublisherBookList</span></code> view itself:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="c1"># views.py</span>
<span class="kn">from</span> <span class="nn">django.shortcuts</span> <span class="k">import</span> <span class="n">get_object_or_404</span>
<span class="kn">from</span> <span class="nn">django.views.generic</span> <span class="k">import</span> <span class="n">ListView</span>
<span class="kn">from</span> <span class="nn">books.models</span> <span class="k">import</span> <span class="n">Book</span><span class="p">,</span> <span class="n">Publisher</span>

<span class="k">class</span> <span class="nc">PublisherBookList</span><span class="p">(</span><span class="n">ListView</span><span class="p">):</span>

    <span class="n">template_name</span> <span class="o">=</span> <span class="s1">&#39;books/books_by_publisher.html&#39;</span>

    <span class="k">def</span> <span class="nf">get_queryset</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">publisher</span> <span class="o">=</span> <span class="n">get_object_or_404</span><span class="p">(</span><span class="n">Publisher</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
        <span class="k">return</span> <span class="n">Book</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">publisher</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">publisher</span><span class="p">)</span>
</pre></div>
</div>
<p>As you can see, it&#8217;s quite easy to add more logic to the queryset selection;
if we wanted, we could use <code class="docutils literal"><span class="pre">self.request.user</span></code> to filter using the current
user, or other more complex logic.</p>
<p>We can also add the publisher into the context at the same time, so we can
use it in the template:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="c1"># ...</span>

<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><span class="n">kwargs</span><span class="p">):</span>
    <span class="c1"># Call the base implementation first to get a context</span>
    <span class="n">context</span> <span class="o">=</span> <span class="nb">super</span><span class="p">(</span><span class="n">PublisherBookList</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">get_context_data</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
    <span class="c1"># Add in the publisher</span>
    <span class="n">context</span><span class="p">[</span><span class="s1">&#39;publisher&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">publisher</span>
    <span class="k">return</span> <span class="n">context</span>
</pre></div>
</div>
</div>
<div class="section" id="s-performing-extra-work">
<span id="s-generic-views-extra-work"></span><span id="performing-extra-work"></span><span id="generic-views-extra-work"></span><h3>Performing extra work<a class="headerlink" href="#performing-extra-work" title="Permalink to this headline">¶</a></h3>
<p>The last common pattern we&#8217;ll look at involves doing some extra work before
or after calling the generic view.</p>
<p>Imagine we had a <code class="docutils literal"><span class="pre">last_accessed</span></code> field on our <code class="docutils literal"><span class="pre">Author</span></code> model that we were
using to keep track of the last time anybody looked at that author:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="c1"># models.py</span>
<span class="kn">from</span> <span class="nn">django.db</span> <span class="k">import</span> <span class="n">models</span>

<span class="k">class</span> <span class="nc">Author</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
    <span class="n">salutation</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">max_length</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span>
    <span class="n">name</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">max_length</span><span class="o">=</span><span class="mi">200</span><span class="p">)</span>
    <span class="n">email</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">EmailField</span><span class="p">()</span>
    <span class="n">headshot</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">ImageField</span><span class="p">(</span><span class="n">upload_to</span><span class="o">=</span><span class="s1">&#39;author_headshots&#39;</span><span class="p">)</span>
    <span class="n">last_accessed</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">DateTimeField</span><span class="p">()</span>
</pre></div>
</div>
<p>The generic <code class="docutils literal"><span class="pre">DetailView</span></code> class, of course, wouldn&#8217;t know anything about this
field, but once again we could easily write a custom view to keep that field
updated.</p>
<p>First, we&#8217;d need to add an author detail bit in the URLconf to point to a
custom view:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.conf.urls</span> <span class="k">import</span> <span class="n">url</span>
<span class="kn">from</span> <span class="nn">books.views</span> <span class="k">import</span> <span class="n">AuthorDetailView</span>

<span class="n">urlpatterns</span> <span class="o">=</span> <span class="p">[</span>
    <span class="c1">#...</span>
    <span class="n">url</span><span class="p">(</span><span class="s1">r&#39;^authors/(?P&lt;pk&gt;[0-9]+)/$&#39;</span><span class="p">,</span> <span class="n">AuthorDetailView</span><span class="o">.</span><span class="n">as_view</span><span class="p">(),</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;author-detail&#39;</span><span class="p">),</span>
<span class="p">]</span>
</pre></div>
</div>
<p>Then we&#8217;d write our new view &#8211; <code class="docutils literal"><span class="pre">get_object</span></code> is the method that retrieves the
object &#8211; so we simply override it and wrap the call:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.views.generic</span> <span class="k">import</span> <span class="n">DetailView</span>
<span class="kn">from</span> <span class="nn">django.utils</span> <span class="k">import</span> <span class="n">timezone</span>
<span class="kn">from</span> <span class="nn">books.models</span> <span class="k">import</span> <span class="n">Author</span>

<span class="k">class</span> <span class="nc">AuthorDetailView</span><span class="p">(</span><span class="n">DetailView</span><span class="p">):</span>

    <span class="n">queryset</span> <span class="o">=</span> <span class="n">Author</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>

    <span class="k">def</span> <span class="nf">get_object</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="c1"># Call the superclass</span>
        <span class="nb">object</span> <span class="o">=</span> <span class="nb">super</span><span class="p">(</span><span class="n">AuthorDetailView</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">get_object</span><span class="p">()</span>
        <span class="c1"># Record the last accessed date</span>
        <span class="nb">object</span><span class="o">.</span><span class="n">last_accessed</span> <span class="o">=</span> <span class="n">timezone</span><span class="o">.</span><span class="n">now</span><span class="p">()</span>
        <span class="nb">object</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
        <span class="c1"># Return the object</span>
        <span class="k">return</span> <span class="nb">object</span>
</pre></div>
</div>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p>The URLconf here uses the named group <code class="docutils literal"><span class="pre">pk</span></code> - this name is the default
name that <code class="docutils literal"><span class="pre">DetailView</span></code> uses to find the value of the primary key used to
filter the queryset.</p>
<p class="last">If you want to call the group something else, you can set <code class="docutils literal"><span class="pre">pk_url_kwarg</span></code>
on the view. More details can be found in the reference for
<a class="reference internal" href="../../ref/class-based-views/generic-display.html#django.views.generic.detail.DetailView" title="django.views.generic.detail.DetailView"><code class="xref py py-class docutils literal"><span class="pre">DetailView</span></code></a></p>
</div>
</div>
</div>
</div>


          </div>
        </div>
      </div>
      
        
          <div class="yui-b" id="sidebar">
            
      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
        <div class="sphinxsidebarwrapper">
  <h3><a href="../../contents.html">Table Of Contents</a></h3>
  <ul>
<li><a class="reference internal" href="#">Built-in class-based generic views</a><ul>
<li><a class="reference internal" href="#extending-generic-views">Extending generic views</a></li>
<li><a class="reference internal" href="#generic-views-of-objects">Generic views of objects</a><ul>
<li><a class="reference internal" href="#making-friendly-template-contexts">Making &#8220;friendly&#8221; template contexts</a></li>
<li><a class="reference internal" href="#adding-extra-context">Adding extra context</a></li>
<li><a class="reference internal" href="#viewing-subsets-of-objects">Viewing subsets of objects</a></li>
<li><a class="reference internal" href="#dynamic-filtering">Dynamic filtering</a></li>
<li><a class="reference internal" href="#performing-extra-work">Performing extra work</a></li>
</ul>
</li>
</ul>
</li>
</ul>

  <h3>Browse</h3>
  <ul>
    
      <li>Prev: <a href="intro.html">Introduction to class-based views</a></li>
    
    
      <li>Next: <a href="generic-editing.html">Form handling with class-based views</a></li>
    
  </ul>
  <h3>You are here:</h3>
  <ul>
      <li>
        <a href="../../index.html">Django 1.8.19 documentation</a>
        
          <ul><li><a href="../index.html">Using Django</a>
        
          <ul><li><a href="index.html">Class-based views</a>
        
        <ul><li>Built-in class-based generic views</li></ul>
        </li></ul></li></ul>
      </li>
  </ul>

  <div role="note" aria-label="source link">
    <h3>This Page</h3>
    <ul class="this-page-menu">
      <li><a href="../../_sources/topics/class-based-views/generic-display.txt"
            rel="nofollow">Show Source</a></li>
    </ul>
   </div>
<div id="searchbox" style="display: none" role="search">
  <h3>Quick search</h3>
    <form class="search" action="../../search.html" method="get">
      <div><input type="text" name="q" /></div>
      <div><input type="submit" value="Go" /></div>
      <input type="hidden" name="check_keywords" value="yes" />
      <input type="hidden" name="area" value="default" />
    </form>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div>
              <h3>Last update:</h3>
              <p class="topless">Mar 10, 2018</p>
          </div>
        
      
    </div>

    <div id="ft">
      <div class="nav">
    &laquo; <a href="intro.html" title="Introduction to class-based views">previous</a>
     |
    <a href="../index.html" title="Using Django" accesskey="U">up</a>
   |
    <a href="generic-editing.html" title="Form handling with class-based views">next</a> &raquo;</div>
    </div>
  </div>

      <div class="clearer"></div>
    </div>
  </body>
</html>