Generic views django

Generic views django DEFAULT

Documentation

Subclassing generic views¶

The second, more powerful way to use generic views is to inherit from an existing view and override attributes (such as the ) or methods (such as ) in your subclass to provide new values or methods. Consider, for example, a view that just displays one template, . Django has a generic view to do this - - so we can subclass it, and override the template name:

# some_app/views.pyfromdjango.views.genericimportTemplateViewclassAboutView(TemplateView):template_name="about.html"

Then we need to add this new view into our URLconf. is a class, not a function, so we point the URL to the class method instead, which provides a function-like entry to class-based views:

# urls.pyfromdjango.urlsimportpathfromsome_app.viewsimportAboutViewurlpatterns=[path('about/',AboutView.as_view()),]

For more information on how to use the built in generic views, consult the next topic on generic class-based views.

Supporting other HTTP methods¶

Suppose somebody wants to access our book library over HTTP using the views as an API. The API client would connect every now and then and download book data for the books published since last visit. But if no new books appeared since then, it is a waste of CPU time and bandwidth to fetch the books from the database, render a full response and send it to the client. It might be preferable to ask the API when the most recent book was published.

We map the URL to book list view in the URLconf:

fromdjango.urlsimportpathfrombooks.viewsimportBookListViewurlpatterns=[path('books/',BookListView.as_view()),]

And the view:

fromdjango.httpimportHttpResponsefromdjango.views.genericimportListViewfrombooks.modelsimportBookclassBookListView(ListView):model=Bookdefhead(self,*args,**kwargs):last_book=self.get_queryset().latest('publication_date')response=HttpResponse(# RFC 1123 date format.headers={'Last-Modified':last_book.publication_date.strftime('%a, %d %b %Y %H:%M:%S GMT')},)returnresponse

If the view is accessed from a request, an object list is returned in the response (using the template). But if the client issues a request, the response has an empty body and the header indicates when the most recent book was published. Based on this information, the client may or may not download the full object list.

Sours: https://docs.djangoproject.com/en/3.2/topics/class-based-views/

Documentation

Generic views of objects¶

certainly is useful, but Django’s generic views really shine when it comes to presenting views of your database content. Because it’s such a common task, Django comes with a handful of built-in generic views to help generate list and detail views of objects.

Let’s start by looking at some examples of showing a list of objects or an individual object.

We’ll be using these models:

# models.pyfromdjango.dbimportmodelsclassPublisher(models.Model):name=models.CharField(max_length=30)address=models.CharField(max_length=50)city=models.CharField(max_length=60)state_province=models.CharField(max_length=30)country=models.CharField(max_length=50)website=models.URLField()classMeta:ordering=["-name"]def__str__(self):returnself.nameclassAuthor(models.Model):salutation=models.CharField(max_length=10)name=models.CharField(max_length=200)email=models.EmailField()headshot=models.ImageField(upload_to='author_headshots')def__str__(self):returnself.nameclassBook(models.Model):title=models.CharField(max_length=100)authors=models.ManyToManyField('Author')publisher=models.ForeignKey(Publisher,on_delete=models.CASCADE)publication_date=models.DateField()

Now we need to define a view:

# views.pyfromdjango.views.genericimportListViewfrombooks.modelsimportPublisherclassPublisherListView(ListView):model=Publisher

Finally hook that view into your urls:

# urls.pyfromdjango.urlsimportpathfrombooks.viewsimportPublisherListViewurlpatterns=[path('publishers/',PublisherListView.as_view()),]

That’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 attribute to the view, but in the absence of an explicit template Django will infer one from the object’s name. In this case, the inferred template will be – the “books” part comes from the name of the app that defines the model, while the “publisher” bit is the lowercased version of the model’s name.

Note

Thus, when (for example) the option of a backend is set to True in , a template location could be: /path/to/project/books/templates/books/publisher_list.html

This template will be rendered against a context containing a variable called that contains all the publisher objects. A template might look like this:

{%extends"base.html"%}{%blockcontent%}<h2>Publishers</h2><ul>{%forpublisherinobject_list%}<li>{{publisher.name}}</li>{%endfor%}</ul>{%endblock%}

That’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 generic views reference 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.

Making “friendly” template contexts¶

You might have noticed that our sample publisher list template stores all the publishers in a variable named . While this works just fine, it isn’t all that “friendly” to template authors: they have to “just know” that they’re dealing with publishers here.

Well, if you’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 lowercased version of the model class’ name. This is provided in addition to the default entry, but contains exactly the same data, i.e. .

If this still isn’t a good match, you can manually set the name of the context variable. The attribute on a generic view specifies the context variable to use:

# views.pyfromdjango.views.genericimportListViewfrombooks.modelsimportPublisherclassPublisherListView(ListView):model=Publishercontext_object_name='my_favorite_publishers'

Providing a useful is always a good idea. Your coworkers who design templates will thank you.

Adding extra context¶

Often you 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 generic view provides the publisher to the context, but how do we get additional information in that template?

The answer is to subclass and provide your own implementation of the method. The default implementation adds the object being displayed to the template, but you can override it to send more:

fromdjango.views.genericimportDetailViewfrombooks.modelsimportBook,PublisherclassPublisherDetailView(DetailView):model=Publisherdefget_context_data(self,**kwargs):# Call the base implementation first to get a contextcontext=super().get_context_data(**kwargs)# Add in a QuerySet of all the bookscontext['book_list']=Book.objects.all()returncontext

Note

Generally, 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 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’re having trouble, review the method resolution order of your view.

Another consideration is that the context data from class-based generic views will override data provided by context processors; see for an example.

Viewing subsets of objects¶

Now let’s take a closer look at the argument we’ve been using all along. The 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 argument is not the only way to specify the objects that the view will operate upon – you can also specify the list of objects using the argument:

fromdjango.views.genericimportDetailViewfrombooks.modelsimportPublisherclassPublisherDetailView(DetailView):context_object_name='publisher'queryset=Publisher.objects.all()

Specifying is shorthand for saying . However, by using to define a filtered list of objects you can be more specific about the objects that will be visible in the view (see Making queries for more information about objects, and see the class-based views reference for the complete details).

To pick an example, we might want to order a list of books by publication date, with the most recent first:

fromdjango.views.genericimportListViewfrombooks.modelsimportBookclassBookListView(ListView):queryset=Book.objects.order_by('-publication_date')context_object_name='book_list'

That’s a pretty minimal example, but it illustrates the idea nicely. You’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:

fromdjango.views.genericimportListViewfrombooks.modelsimportBookclassAcmeBookListView(ListView):context_object_name='book_list'queryset=Book.objects.filter(publisher__name='ACME Publishing')template_name='books/acme_list.html'

Notice that along with a filtered , we’re also using a custom template name. If we didn’t, the generic view would use the same template as the “vanilla” object list, which might not be what we want.

Also notice that this isn’t a very elegant way of doing publisher-specific books. If we want to add another publisher page, we’d need another handful of lines in the URLconf, and more than a few publishers would get unreasonable. We’ll deal with this problem in the next section.

Note

If you get a 404 when requesting , check to ensure you actually have a Publisher with the name ‘ACME Publishing’. Generic views have an parameter for this case. See the class-based-views reference for more details.

Dynamic filtering¶

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’s name in the URLconf, but what if we wanted to write a view that displayed all the books by some arbitrary publisher?

Handily, the has a method we can override. By default, it returns the value of the attribute, but we can use it to add more logic.

The key part to making this work is that when class-based views are called, various useful things are stored on ; as well as the request () this includes the positional () and name-based () arguments captured according to the URLconf.

Here, we have a URLconf with a single captured group:

# urls.pyfromdjango.urlsimportpathfrombooks.viewsimportPublisherBookListViewurlpatterns=[path('books/<publisher>/',PublisherBookListView.as_view()),]

Next, we’ll write the view itself:

# views.pyfromdjango.shortcutsimportget_object_or_404fromdjango.views.genericimportListViewfrombooks.modelsimportBook,PublisherclassPublisherBookListView(ListView):template_name='books/books_by_publisher.html'defget_queryset(self):self.publisher=get_object_or_404(Publisher,name=self.kwargs['publisher'])returnBook.objects.filter(publisher=self.publisher)

Using to add logic to the queryset selection is as convenient as it is powerful. For instance, if we wanted, we could use to filter using the current user, or other more complex logic.

We can also add the publisher into the context at the same time, so we can use it in the template:

# ...defget_context_data(self,**kwargs):# Call the base implementation first to get a contextcontext=super().get_context_data(**kwargs)# Add in the publishercontext['publisher']=self.publisherreturncontext

Performing extra work¶

The last common pattern we’ll look at involves doing some extra work before or after calling the generic view.

Imagine we had a field on our model that we were using to keep track of the last time anybody looked at that author:

# models.pyfromdjango.dbimportmodelsclassAuthor(models.Model):salutation=models.CharField(max_length=10)name=models.CharField(max_length=200)email=models.EmailField()headshot=models.ImageField(upload_to='author_headshots')last_accessed=models.DateTimeField()

The generic class wouldn’t know anything about this field, but once again we could write a custom view to keep that field updated.

First, we’d need to add an author detail bit in the URLconf to point to a custom view:

fromdjango.urlsimportpathfrombooks.viewsimportAuthorDetailViewurlpatterns=[#...path('authors/<int:pk>/',AuthorDetailView.as_view(),name='author-detail'),]

Then we’d write our new view – is the method that retrieves the object – so we override it and wrap the call:

fromdjango.utilsimporttimezonefromdjango.views.genericimportDetailViewfrombooks.modelsimportAuthorclassAuthorDetailView(DetailView):queryset=Author.objects.all()defget_object(self):obj=super().get_object()# Record the last accessed dateobj.last_accessed=timezone.now()obj.save()returnobj

Note

The URLconf here uses the named group - this name is the default name that uses to find the value of the primary key used to filter the queryset.

If you want to call the group something else, you can set on the view.

Sours: https://docs.djangoproject.com/en/3.2/topics/class-based-views/generic-display/
  1. Chinese stone seal
  2. Dodge minivan v8
  3. Minecraft house boat
  4. Patc transmission

Django Tutorial Part 6: Generic list and detail views

This tutorial extends our LocalLibrary website, adding list and detail pages for books and authors. Here we'll learn about generic class-based views, and show how they can reduce the amount of code you have to write for common use cases. We'll also go into URL handling in greater detail, showing how to perform basic pattern matching.

Prerequisites: Complete all previous tutorial topics, including Django Tutorial Part 5: Creating our home page.
Objective: To understand where and how to use generic class-based views, and how to extract patterns from URLs and pass the information to views.

Overview

In this tutorial we're going to complete the first version of the LocalLibrary website by adding list and detail pages for books and authors (or to be more precise, we'll show you how to implement the book pages, and get you to create the author pages yourself!)

The process is similar to creating the index page, which we showed in the previous tutorial. We'll still need to create URL maps, views, and templates. The main difference is that for the detail pages, we'll have the additional challenge of extracting information from patterns in the URL and passing it to the view. For these pages, we're going to demonstrate a completely different type of view: generic class-based list and detail views. These can significantly reduce the amount of view code needed, making them easier to write and maintain.

The final part of the tutorial will demonstrate how to paginate your data when using generic class-based list views.

Book list page

The book list page will display a list of all the available book records in the page, accessed using the URL: . The page will display a title and author for each record, with the title being a hyperlink to the associated book detail page. The page will have the same structure and navigation as all other pages in the site, and we can, therefore, extend the base template (base_generic.html) we created in the previous tutorial.

URL mapping

Open /catalog/urls.py and copy in the line setting the path for , as shown below. Just as for the index page, this function defines a pattern to match against the URL ('books/'), a view function that will be called if the URL matches (), and a name for this particular mapping.

As discussed in the previous tutorial the URL must already have matched , so the view will actually be called for the URL: .

The view function has a different format than before — that's because this view will actually be implemented as a class. We will be inheriting from an existing generic view function that already does most of what we want this view function to do, rather than writing our own from scratch.

For Django class-based views we access an appropriate view function by calling the class method . This does all the work of creating an instance of the class, and making sure that the right handler methods are called for incoming HTTP requests.

View (class-based)

We could quite easily write the book list view as a regular function (just like our previous index view), which would query the database for all books, and then call to pass the list to a specified template. Instead, however, we're going to use a class-based generic list view () — a class that inherits from an existing view. Because the generic view already implements most of the functionality we need and follows Django best-practice, we will be able to create a more robust list view with less code, less repetition, and ultimately less maintenance.

Open catalog/views.py, and copy the following code into the bottom of the file:

That's it! The generic view will query the database to get all records for the specified model () then render a template located at /locallibrary/catalog/templates/catalog/book_list.html (which we will create below). Within the template you can access the list of books with the template variable named OR (i.e. generically "").

Note: This awkward path for the template location isn't a misprint — the generic views look for templates in ( in this case) inside the application's directory (.

You can add attributes to change the default behavior above. For example, you can specify another template file if you need to have multiple views that use this same model, or you might want to use a different template variable name if is not intuitive for your particular template use-case. Possibly the most useful variation is to change/filter the subset of results that are returned — so instead of listing all books you might list top 5 books that were read by other users.

Overriding methods in class-based views

While we don't need to do so here, you can also override some of the class methods.

For example, we can override the  method to change the list of records returned. This is more flexible than just setting the attribute as we did in the preceding code fragment (though there is no real benefit in this case):

We might also override  in order to pass additional context variables to the template (e.g. the list of books is passed by default). The fragment below shows how to add a variable named "" to the context (it would then be available as a template variable).

When doing this it is important to follow the pattern used above:

  • First get the existing context from our superclass.
  • Then add your new context information.
  • Then return the new (updated) context.

Creating the List View template

Create the HTML file /locallibrary/catalog/templates/catalog/book_list.html and copy in the text below. As discussed above, this is the default template file expected by the generic class-based list view (for a model named in an application named ).

Templates for generic views are just like any other templates (although of course the context/information passed to the template may differ). As with our index template, we extend our base template in the first line and then replace the block named .

The view passes the context (list of books) by default as and aliases; either will work.

Conditional execution

We use the , , and template tags to check whether the has been defined and is not empty. If  is empty, then the  clause displays text explaining that there are no books to list. If  is not empty, then we iterate through the list of books.

The condition above only checks for one case, but you can test on additional conditions using the template tag (e.g. ). For more information about conditional operators see: if, ifequal/ifnotequal, and ifchanged in Built-in template tags and filters (Django Docs).

For loops

The template uses the for and template tags to loop through the book list, as shown below. Each iteration populates the template variable with information for the current list item.

While not used here, within the loop Django will also create other variables that you can use to track the iteration. For example, you can test the variable to perform conditional processing the last time that the loop is run.

Accessing variables

The code inside the loop creates a list item for each book that shows both the title (as a link to the yet-to-be-created detail view) and the author.

We access the fields of the associated book record using the "dot notation" (e.g. and ), where the text following the item is the field name (as defined in the model).

We can also call functions in the model from within our template — in this case we call to get a URL you could use to display the associated detail record. This works provided the function does not have any arguments (there is no way to pass arguments!)

Note: We have to be a little careful of "side effects" when calling functions in templates. Here we just get a URL to display, but a function can do pretty much anything — we wouldn't want to delete our database (for example) just by rendering our template!

Update the base template

Open the base template (/locallibrary/catalog/templates/base_generic.html) and insert {% url 'books' %} into the URL link for All books, as shown below. This will enable the link in all pages (we can successfully put this in place now that we've created the "books" URL mapper).

What does it look like?

You won't be able to build the book list yet, because we're still missing a dependency — the URL map for the book detail pages, which is needed to create hyperlinks to individual books. We'll show both list and detail views after the next section.

Book detail page

The book detail page will display information about a specific book, accessed using the URL (where is the primary key for the book). In addition to fields in the model (author, summary, ISBN, language, and genre), we'll also list the details of the available copies () including the status, expected return date, imprint, and id. This will allow our readers to not only learn about the book, but also to confirm whether/when it is available.

URL mapping

Open /catalog/urls.py and add the path named 'book-detail' shown below. This function defines a pattern, associated generic class-based detail view, and a name.

For the book-detail path the URL pattern uses a special syntax to capture the specific id of the book that we want to see. The syntax is very simple: angle brackets define the part of the URL to be captured, enclosing the name of the variable that the view can use to access the captured data. For example, <something> , will capture the marked pattern and pass the value to the view as a variable "something". You can optionally precede the variable name with a converter specification that defines the type of data (int, str, slug, uuid, path).

In this case we use to capture the book id, which must be a specially formatted string and pass it to the view as a parameter named  (short for primary key). This is the id that is being used to store the book uniquely in the database, as defined in the Book Model.

Note: As discussed previously, our matched URL is actually (because we are in the catalog application, is assumed).

Warning: The generic class-based detail view expects to be passed a parameter named pk. If you're writing your own function view you can use whatever parameter name you like, or indeed pass the information in an unnamed argument.

Advanced path matching/regular expression primer

Note: You won't need this section to complete the tutorial! We provide it because knowing this option is likely to be useful in your Django-centric future.

The pattern matching provided by is simple and useful for the (very common) cases where you just want to capture any string or integer. If you need more refined filtering (for example, to filter only strings that have a certain number of characters) then you can use the re_path() method.

This method is used just like  except that it allows you to specify a pattern using a Regular expression. For example, the previous path could have been written as shown below:

Regular expressions are an incredibly powerful pattern mapping tool. They are, frankly, quite unintuitive and can be intimidating for beginners. Below is a very short primer!

The first thing to know is that regular expressions should usually be declared using the raw string literal syntax (i.e. they are enclosed as shown: r'<your regular expression text goes here>').

The main parts of the syntax you will need to know for declaring the pattern matches are:

SymbolMeaning
^Match the beginning of the text
$Match the end of the text
\dMatch a digit (0, 1, 2, ... 9)
\w Match a word character, e.g. any upper- or lower-case character in the alphabet, digit or the underscore character (_)
+ Match one or more of the preceding character. For example, to match one or more digits you would use . To match one or more "a" characters, you could use
* Match zero or more of the preceding character. For example, to match nothing or a word you could use
( ) Capture the part of the pattern inside the brackets. Any captured values will be passed to the view as unnamed parameters (if multiple patterns are captured, the associated parameters will be supplied in the order that the captures were declared).
(?P<name>...) Capture the pattern (indicated by ...) as a named variable (in this case "name"). The captured values are passed to the view with the name specified. Your view must therefore declare a parameter with the same name!
[  ] Match against one character in the set. For example, [abc] will match on 'a' or 'b' or 'c'. [-\w] will match on the '-' character or any word character.

Most other characters can be taken literally!

Let's consider a few real examples of patterns:

PatternDescription
r'^book/(?P<pk>\d+)$'

This is the RE used in our URL mapper. It matches a string that has at the start of the line (^book/), then has one or more digits (), and then ends (with no non-digit characters before the end of line marker).

It also captures all the digits (?P<pk>\d+) and passes them to the view in a parameter named 'pk'. The captured values are always passed as a string!

For example, this would match , and send a variable to the view.

r'^book/(\d+)$' This matches the same URLs as the preceding case. The captured information would be sent as an unnamed argument to the view.
r'^book/(?P<stub>[-\w]+)$'

This matches a string that has at the start of the line (^book/), then has one or more characters that are either a '-' or a word character ([-\w]+), and then ends. It also captures this set of characters and passes them to the view in a parameter named 'stub'.

This is a fairly typical pattern for a "stub". Stubs are URL-friendly word-based primary keys for data. You might use a stub if you wanted your book URL to be more informative. For example rather than .

You can capture multiple patterns in the one match, and hence encode lots of different information in a URL.

Note: As a challenge, consider how you might encode a URL to list all books released in a particular year, month, day, and the RE that could be used to match it.

Passing additional options in your URL maps

One feature that we haven't used here, but which you may find valuable, is that you can pass a dictionary containing additional options to the view (using the third un-named argument to the function). This approach can be useful if you want to use the same view for multiple resources, and pass data to configure its behavior in each case.

For example, given the path shown below, for a request to Django will call .

Note: Both named captured patterns and dictionary options are passed to the view as named arguments. If you use the same name for both a capture pattern and a dictionary key, then the dictionary option will be used.

View (class-based)

Open catalog/views.py, and copy the following code into the bottom of the file:

That's it! All you need to do now is create a template called /locallibrary/catalog/templates/catalog/book_detail.html, and the view will pass it the database information for the specific record extracted by the URL mapper. Within the template you can access the book's details with the template variable named OR (i.e. generically "").

If you need to, you can change the template used and the name of the context object used to reference the book in the template. You can also override methods to, for example, add additional information to the context.

What happens if the record doesn't exist?

If a requested record does not exist then the generic class-based detail view will raise an exception for you automatically — in production, this will automatically display an appropriate "resource not found" page, which you can customise if desired.

Just to give you some idea of how this works, the code fragment below demonstrates how you would implement the class-based view as a function if you were not using the generic class-based detail view.

The view first tries to get the specific book record from the model. If this fails the view should raise an exception to indicate that the book is "not found". The final step is then, as usual, to call with the template name and the book data in the parameter (as a dictionary).

Alternatively, we can use the function as a shortcut to raise an exception if the record is not found.

Creating the Detail View template

Create the HTML file /locallibrary/catalog/templates/catalog/book_detail.html and give it the below content. As discussed above, this is the default template file name expected by the generic class-based detail view (for a model named in an application named ).

Note: The author link in the template above has an empty URL because we've not yet created an author detail page to link to. Once the detail page exists we can get its URL with either of these two approaches:

  • Use the template tag to reverse the 'author-detail' URL (defined in the URL mapper), passing it the author instance for the book:
  • Call the author model's method (this performs the same reversing operation):
    <a href="{{ book.author.get_absolute_url }}">{{ book.author }}</a>

While both methods effectively do the same thing, is preferred because it helps you write more consistent and maintainable code (any changes only need to be done in one place: the author model).

Though a little larger, almost everything in this template has been described previously:

  • We extend our base template and override the "content" block.
  • We use conditional processing to determine whether or not to display specific content.
  • We use loops to loop through lists of objects.
  • We access the context fields using the dot notation (because we've used the detail generic view, the context is named ; we could also use "")

The first interesting thing we haven't seen before is the function . This method is "automagically" constructed by Django in order to return the set of records associated with a particular .

This method is needed because you declare a  (one-to many) field in only the "one" side of the relationship (the ). Since you don't do anything to declare the relationship in the other ("many") models, it (the ) doesn't have any field to get the set of associated records. To overcome this problem, Django constructs an appropriately named "reverse lookup" function that you can use. The name of the function is constructed by lower-casing the model name where the  was declared, followed by (i.e. so the function created in is ).

Note: Here we use to get all records (the default). While you can use the method to get a subset of records in code, you can't do this directly in templates because you can't specify arguments to functions.

Beware also that if you don't define an order (on your class-based view or model), you will also see errors from the development server like this one:

[29/May/2017 18:37:53] "GET /catalog/books/?page=1 HTTP/1.1" 200 1637 /foo/local_library/venv/lib/python3.5/site-packages/django/views/generic/list.py:99: UnorderedObjectListWarning: Pagination may yield inconsistent results with an unordered object_list: <QuerySet [<Author: Ortiz, David>, <Author: H. McRaven, William>, <Author: Leigh, Melinda>]> allow_empty_first_page=allow_empty_first_page, **kwargs)

That happens because the paginator object expects to see some ORDER BY being executed on your underlying database. Without it, it can't be sure the records being returned are actually in the right order!

This tutorial hasn't covered Pagination (yet!), but since you can't use and pass a parameter (the same with described above) you will have to choose between three choices:

  1. Add a inside a declaration on your model.
  2. Add a attribute in your custom class-based view, specifying an .
  3. Adding a method to your custom class-based view and also specify the .

If you decide to go with a for the model (probably not as flexible as customizing the class-based view, but easy enough), you will end up with something like this:

Of course, the field doesn't need to be : it could be any other.

Last but not least, you should sort by an attribute/column that actually has an index (unique or not) on your database to avoid performance issues. Of course, this will not be necessary here (we are probably getting ahead of ourselves with so few books and users), but it is something worth keeping in mind for future projects.

The second interesting (and non-obvious) thing in the template is where we set a class (, , ) to color-code the human readable status text for each book instance ("available", "maintenance", etc.). Astute readers will note that the method  that we use to get the status text does not appear elsewhere in the code.

This function is automatically created because is a choices field. Django automatically creates a method  for every choices field "" in a model, which can be used to get the current value of the field.

What does it look like?

At this point, we should have created everything needed to display both the book list and book detail pages. Run the server () and open your browser to http://127.0.0.1:8000/.

Warning: Don't click any author or author detail links yet — you'll create those in the challenge!

Click the All books link to display the list of books.

Book List Page

Then click a link to one of your books. If everything is set up correctly, you should see something like the following screenshot.

Book Detail Page

If you've just got a few records, our book list page will look fine. However, as you get into the tens or hundreds of records the page will take progressively longer to load (and have far too much content to browse sensibly). The solution to this problem is to add pagination to your list views, reducing the number of items displayed on each page.

Django has excellent inbuilt support for pagination. Even better, this is built into the generic class-based list views so you don't have to do very much to enable it!

Views

Open catalog/views.py, and add the line shown below.

With this addition, as soon as you have more than 10 records the view will start paginating the data it sends to the template. The different pages are accessed using GET parameters — to access page 2 you would use the URL .

Templates

Now that the data is paginated, we need to add support to the template to scroll through the results set. Because we might want paginate all list views, we'll add this to the base template.

Open /locallibrary/catalog/templates/base_generic.html and find the "content block" (as shown below).

Copy in the following pagination block immediately following the . The code first checks if pagination is enabled on the current page. If so, it adds next and previous links as appropriate (and the current page number).

The is a Paginator object that will exist if pagination is being used on the current page. It allows you to get all the information about the current page, previous pages, how many pages there are, etc.

We use to get the current page URL for creating the pagination links. This is useful because it is independent of the object that we're paginating.

That's it!

What does it look like?

The screenshot below shows what the pagination looks like — if you haven't entered more than 10 titles into your database, then you can test it more easily by lowering the number specified in the line in your catalog/views.py file. To get the below result we changed it to .

The pagination links are displayed on the bottom, with next/previous links being displayed depending on which page you're on.

Book List Page - paginated

Challenge yourself

The challenge in this article is to create the author detail and list views required to complete the project. These should be made available at the following URLs:

  •  — The list of all authors.
  • — The detail view for the specific author with a primary key field named 

The code required for the URL mappers and the views should be virtually identical to the list and detail views we created above. The templates will be different but will share similar behavior.

Note:

  • Once you've created the URL mapper for the author list page you will also need to update the All authors link in the base template. Follow the same process as we did when we updated the All books link.
  • Once you've created the URL mapper for the author detail page, you should also update the book detail view template (/locallibrary/catalog/templates/catalog/book_detail.html) so that the author link points to your new author detail page (rather than being an empty URL). The recommended way to do this is to call on the author model as shown below.

When you are finished, your pages should look something like the screenshots below.

Author List Page

Author Detail Page

Summary

Congratulations, our basic library functionality is now complete!

In this article, we've learned how to use the generic class-based list and detail views and used them to create pages to view our books and authors. Along the way we've learned about pattern matching with regular expressions, and how you can pass data from URLs to your views. We've also learned a few more tricks for using templates. Last of all we've shown how to paginate list views so that our lists are manageable even when we have many records.

In our next articles, we'll extend this library to support user accounts, and thereby demonstrate user authentication, permissions, sessions, and forms.

See also

In this module

Sours: https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Generic_views
Introdução às Class Based Views

Documentation

A page representing a list of objects.

While this view is executing, will contain the list of objects (usually, but not necessarily a queryset) that the view is operating upon.

Ancestors (MRO)

This view inherits methods and attributes from the following views:

Method Flowchart

Example views.py:

fromdjango.utilsimporttimezonefromdjango.views.generic.listimportListViewfromarticles.modelsimportArticleclassArticleListView(ListView):model=Articlepaginate_by=100# if pagination is desireddefget_context_data(self,**kwargs):context=super().get_context_data(**kwargs)context['now']=timezone.now()returncontext

Example myapp/urls.py:

fromdjango.urlsimportpathfromarticle.viewsimportArticleListViewurlpatterns=[path('',ArticleListView.as_view(),name='article-list'),]

Example myapp/article_list.html:

<h1>Articles</h1><ul>{%forarticleinobject_list%}<li>{{article.pub_date|date}} - {{article.headline}}</li>{%empty%}<li>No articles yet.</li>{%endfor%}</ul>

If you’re using pagination, you can adapt the example template from the pagination docs. Change instances of in that example template to .

Sours: https://docs.djangoproject.com/en/3.2/ref/class-based-views/generic-display/

Views django generic

Generic views

mixins.pygenerics.py

Django’s generic views... were developed as a shortcut for common usage patterns... 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 repeat yourself.

— Django Documentation

One of the key benefits of class-based views is the way they allow you to compose bits of reusable behavior. REST framework takes advantage of this by providing a number of pre-built views that provide for commonly used patterns.

The generic views provided by REST framework allow you to quickly build API views that map closely to your database models.

If the generic views don't suit the needs of your API, you can drop down to using the regular class, or reuse the mixins and base classes used by the generic views to compose your own set of reusable generic views.

Examples

Typically when using the generic views, you'll override the view, and set several class attributes.

For more complex cases you might also want to override various methods on the view class. For example.

For very simple cases you might want to pass through any class attributes using the method. For example, your URLconf might include something like the following entry:


GenericAPIView

This class extends REST framework's class, adding commonly required behavior for standard list and detail views.

Each of the concrete generic views provided is built by combining , with one or more mixin classes.

Attributes

Basic settings:

The following attributes control the basic view behavior.

  • - The queryset that should be used for returning objects from this view. Typically, you must either set this attribute, or override the method. If you are overriding a view method, it is important that you call instead of accessing this property directly, as will get evaluated once, and those results will be cached for all subsequent requests.
  • - The serializer class that should be used for validating and deserializing input, and for serializing output. Typically, you must either set this attribute, or override the method.
  • - The model field that should be used to for performing object lookup of individual model instances. Defaults to . Note that when using hyperlinked APIs you'll need to ensure that both the API views and the serializer classes set the lookup fields if you need to use a custom value.
  • - The URL keyword argument that should be used for object lookup. The URL conf should include a keyword argument corresponding to this value. If unset this defaults to using the same value as .

Pagination:

The following attributes are used to control pagination when used with list views.

  • - The pagination class that should be used when paginating list results. Defaults to the same value as the setting, which is . Setting will disable pagination on this view.

Filtering:

  • - A list of filter backend classes that should be used for filtering the queryset. Defaults to the same value as the setting.

Methods

Base methods:

Returns the queryset that should be used for list views, and that should be used as the base for lookups in detail views. Defaults to returning the queryset specified by the attribute.

This method should always be used rather than accessing directly, as gets evaluated only once, and those results are cached for all subsequent requests.

May be overridden to provide dynamic behavior, such as returning a queryset, that is specific to the user making the request.

For example:

Returns an object instance that should be used for detail views. Defaults to using the parameter to filter the base queryset.

May be overridden to provide more complex behavior, such as object lookups based on more than one URL kwarg.

For example:

Note that if your API doesn't include any object level permissions, you may optionally exclude the , and simply return the object from the lookup.

Given a queryset, filter it with whichever filter backends are in use, returning a new queryset.

For example:

Returns the class that should be used for the serializer. Defaults to returning the attribute.

May be overridden to provide dynamic behavior, such as using different serializers for read and write operations, or providing different serializers to different types of users.

For example:

Save and deletion hooks:

The following methods are provided by the mixin classes, and provide easy overriding of the object save or deletion behavior.

  • - Called by when saving a new object instance.
  • - Called by when saving an existing object instance.
  • - Called by when deleting an object instance.

These hooks are particularly useful for setting attributes that are implicit in the request, but are not part of the request data. For instance, you might set an attribute on the object based on the request user, or based on a URL keyword argument.

These override points are also particularly useful for adding behavior that occurs before or after saving an object, such as emailing a confirmation, or logging the update.

You can also use these hooks to provide additional validation, by raising a . This can be useful if you need some validation logic to apply at the point of database save. For example:

Other methods:

You won't typically need to override the following methods, although you might need to call into them if you're writing custom views using .

  • - Returns a dictionary containing any extra context that should be supplied to the serializer. Defaults to including , and keys.
  • - Returns a serializer instance.
  • - Returns a paginated style object.
  • - Paginate a queryset if required, either returning a page object, or if pagination is not configured for this view.
  • - Given a queryset, filter it with whichever filter backends are in use, returning a new queryset.

The mixin classes provide the actions that are used to provide the basic view behavior. Note that the mixin classes provide action methods rather than defining the handler methods, such as and , directly. This allows for more flexible composition of behavior.

The mixin classes can be imported from .

ListModelMixin

Provides a method, that implements listing a queryset.

If the queryset is populated, this returns a response, with a serialized representation of the queryset as the body of the response. The response data may optionally be paginated.

CreateModelMixin

Provides a method, that implements creating and saving a new model instance.

If an object is created this returns a response, with a serialized representation of the object as the body of the response. If the representation contains a key named , then the header of the response will be populated with that value.

If the request data provided for creating the object was invalid, a response will be returned, with the error details as the body of the response.

RetrieveModelMixin

Provides a method, that implements returning an existing model instance in a response.

If an object can be retrieved this returns a response, with a serialized representation of the object as the body of the response. Otherwise it will return a .

UpdateModelMixin

Provides a method, that implements updating and saving an existing model instance.

Also provides a method, which is similar to the method, except that all fields for the update will be optional. This allows support for HTTP requests.

If an object is updated this returns a response, with a serialized representation of the object as the body of the response.

If the request data provided for updating the object was invalid, a response will be returned, with the error details as the body of the response.

DestroyModelMixin

Provides a method, that implements deletion of an existing model instance.

If an object is deleted this returns a response, otherwise it will return a .


The following classes are the concrete generic views. If you're using generic views this is normally the level you'll be working at unless you need heavily customized behavior.

The view classes can be imported from .

CreateAPIView

Used for create-only endpoints.

Provides a method handler.

Extends: GenericAPIView, CreateModelMixin

ListAPIView

Used for read-only endpoints to represent a collection of model instances.

Provides a method handler.

Extends: GenericAPIView, ListModelMixin

RetrieveAPIView

Used for read-only endpoints to represent a single model instance.

Provides a method handler.

Extends: GenericAPIView, RetrieveModelMixin

DestroyAPIView

Used for delete-only endpoints for a single model instance.

Provides a method handler.

Extends: GenericAPIView, DestroyModelMixin

UpdateAPIView

Used for update-only endpoints for a single model instance.

Provides and method handlers.

Extends: GenericAPIView, UpdateModelMixin

ListCreateAPIView

Used for read-write endpoints to represent a collection of model instances.

Provides and method handlers.

Extends: GenericAPIView, ListModelMixin, CreateModelMixin

RetrieveUpdateAPIView

Used for read or update endpoints to represent a single model instance.

Provides , and method handlers.

Extends: GenericAPIView, RetrieveModelMixin, UpdateModelMixin

RetrieveDestroyAPIView

Used for read or delete endpoints to represent a single model instance.

Provides and method handlers.

Extends: GenericAPIView, RetrieveModelMixin, DestroyModelMixin

RetrieveUpdateDestroyAPIView

Used for read-write-delete endpoints to represent a single model instance.

Provides , , and method handlers.

Extends: GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin


Often you'll want to use the existing generic views, but use some slightly customized behavior. If you find yourself reusing some bit of customized behavior in multiple places, you might want to refactor the behavior into a common class that you can then just apply to any view or viewset as needed.

Creating custom mixins

For example, if you need to lookup objects based on multiple fields in the URL conf, you could create a mixin class like the following:

You can then simply apply this mixin to a view or viewset anytime you need to apply the custom behavior.

Using custom mixins is a good option if you have custom behavior that needs to be used.

Creating custom base classes

If you are using a mixin across multiple views, you can take this a step further and create your own set of base views that can then be used throughout your project. For example:

Using custom base classes is a good option if you have custom behavior that consistently needs to be repeated across a large number of views throughout your project.


Prior to version 3.0 the REST framework mixins treated as either an update or a create operation, depending on if the object already existed or not.

Allowing as create operations is problematic, as it necessarily exposes information about the existence or non-existence of objects. It's also not obvious that transparently allowing re-creating of previously deleted instances is necessarily a better default behavior than simply returning responses.

Both styles " as 404" and " as create" can be valid in different circumstances, but from version 3.0 onwards we now use 404 behavior as the default, due to it being simpler and more obvious.

If you need to generic PUT-as-create behavior you may want to include something like this class as a mixin to your views.


The following third party packages provide additional generic view implementations.

Django Rest Multiple Models

Django Rest Multiple Models provides a generic view (and mixin) for sending multiple serialized models and/or querysets via a single API request.

Sours: https://www.django-rest-framework.org/api-guide/generic-views/
Django Tutorial for Beginners - 29 - Generic Views

Classy Class-Based Views.

What are class-based views anyway?

Django's class-based generic views provide abstract classes implementing common web development tasks. These are very powerful, and heavily-utilise Python's object orientation and multiple inheritance in order to be extensible. This means they're more than just a couple of generic shortcuts — they provide utilities which can be mixed into the much more complex views that you write yourself.

Great! So what's the problem?

All of this power comes at the expense of simplicity. For example, trying to work out exactly which method you need to customise, and what its keyword arguments are, on your can feel a little like wading through spaghetti — it has 10 separate ancestors (plus ), spread across 3 different python files. This site shows you exactly what you need to know.

How does this site help?

To make things easier, we've taken all the attributes and methods that every view defines or inherits, and flattened all that information onto one comprehensive page per view. Check out UpdateView, for example.

Sours: https://ccbv.co.uk/

Similar news:

Documentation

Class-based views provide an alternative way to implement views as Python objects instead of functions. They do not replace function-based views, but have certain differences and advantages when compared to function-based views:

  • Organization of code related to specific HTTP methods (, , etc.) can be addressed by separate methods instead of conditional branching.
  • Object oriented techniques such as mixins (multiple inheritance) can be used to factor code into reusable components.

The relationship and history of generic views, class-based views, and class-based generic views¶

In the beginning there was only the view function contract, Django passed your function an and expected back an . This was the extent of what Django provided.

Early on it was recognized that there were common idioms and patterns found in view development. Function-based generic views were introduced to abstract these patterns and ease view development for the common cases.

The problem with function-based generic views is that while they covered the simple cases well, there was no way to extend or customize them beyond some configuration options, limiting their usefulness in many real-world applications.

Class-based generic views were created with the same objective as function-based generic views, to make view development easier. However, the way the solution is implemented, through the use of mixins, provides a toolkit that results in class-based generic views being more extensible and flexible than their function-based counterparts.

If you have tried function based generic views in the past and found them lacking, you should not think of class-based generic views as a class-based equivalent, but rather as a fresh approach to solving the original problems that generic views were meant to solve.

The toolkit of base classes and mixins that Django uses to build class-based generic views are built for maximum flexibility, and as such have many hooks in the form of default method implementations and attributes that you are unlikely to be concerned with in the simplest use cases. For example, instead of limiting you to a class-based attribute for , the implementation uses a method, which calls a method, which in its default implementation returns the attribute of the class. This gives you several options for specifying what form to use, from an attribute, to a fully dynamic, callable hook. These options seem to add hollow complexity for simple situations, but without them, more advanced designs would be limited.

Using class-based views¶

At its core, a class-based view allows you to respond to different HTTP request methods with different class instance methods, instead of with conditionally branching code inside a single view function.

So where the code to handle HTTP in a view function would look something like:

fromdjango.httpimportHttpResponsedefmy_view(request):ifrequest.method=='GET':# <view logic>returnHttpResponse('result')

In a class-based view, this would become:

fromdjango.httpimportHttpResponsefromdjango.viewsimportViewclassMyView(View):defget(self,request):# <view logic>returnHttpResponse('result')

Because Django’s URL resolver expects to send the request and associated arguments to a callable function, not a class, class-based views have an class method which returns a function that can be called when a request arrives for a URL matching the associated pattern. The function creates an instance of the class, calls to initialize its attributes, and then calls its method. looks at the request to determine whether it is a , , etc, and relays the request to a matching method if one is defined, or raises if not:

# urls.pyfromdjango.urlsimportpathfrommyapp.viewsimportMyViewurlpatterns=[path('about/',MyView.as_view()),]

It is worth noting that what your method returns is identical to what you return from a function-based view, namely some form of . This means that http shortcuts or objects are valid to use inside a class-based view.

While a minimal class-based view does not require any class attributes to perform its job, class attributes are useful in many class-based designs, and there are two ways to configure or set class attributes.

The first is the standard Python way of subclassing and overriding attributes and methods in the subclass. So that if your parent class had an attribute like this:

fromdjango.httpimportHttpResponsefromdjango.viewsimportViewclassGreetingView(View):greeting="Good Day"defget(self,request):returnHttpResponse(self.greeting)

You can override that in a subclass:

classMorningGreetingView(GreetingView):greeting="Morning to ya"

Another option is to configure class attributes as keyword arguments to the call in the URLconf:

urlpatterns=[path('about/',GreetingView.as_view(greeting="G'day")),]

Note

While your class is instantiated for each request dispatched to it, class attributes set through the entry point are configured only once at the time your URLs are imported.

Using mixins¶

Mixins are a form of multiple inheritance where behaviors and attributes of multiple parent classes can be combined.

For example, in the generic class-based views there is a mixin called whose primary purpose is to define the method . When combined with the behavior of the base class, the result is a class that will dispatch requests to the appropriate matching methods (a behavior defined in the base class), and that has a method that uses a attribute to return a object (a behavior defined in the ).

Mixins are an excellent way of reusing code across multiple classes, but they come with some cost. The more your code is scattered among mixins, the harder it will be to read a child class and know what exactly it is doing, and the harder it will be to know which methods from which mixins to override if you are subclassing something that has a deep inheritance tree.

Note also that you can only inherit from one generic view - that is, only one parent class may inherit from and the rest (if any) should be mixins. Trying to inherit from more than one class that inherits from - for example, trying to use a form at the top of a list and combining and - won’t work as expected.

Handling forms with class-based views¶

A basic function-based view that handles forms may look something like this:

fromdjango.httpimportHttpResponseRedirectfromdjango.shortcutsimportrenderfrom.formsimportMyFormdefmyview(request):ifrequest.method=="POST":form=MyForm(request.POST)ifform.is_valid():# <process form cleaned data>returnHttpResponseRedirect('/success/')else:form=MyForm(initial={'key':'value'})returnrender(request,'form_template.html',{'form':form})

A similar class-based view might look like:

fromdjango.httpimportHttpResponseRedirectfromdjango.shortcutsimportrenderfromdjango.viewsimportViewfrom.formsimportMyFormclassMyFormView(View):form_class=MyForminitial={'key':'value'}template_name='form_template.html'defget(self,request,*args,**kwargs):form=self.form_class(initial=self.initial)returnrender(request,self.template_name,{'form':form})defpost(self,request,*args,**kwargs):form=self.form_class(request.POST)ifform.is_valid():# <process form cleaned data>returnHttpResponseRedirect('/success/')returnrender(request,self.template_name,{'form':form})

This is a minimal case, but you can see that you would then have the option of customizing this view by overriding any of the class attributes, e.g. , via URLconf configuration, or subclassing and overriding one or more of the methods (or both!).

Decorating class-based views¶

The extension of class-based views isn’t limited to using mixins. You can also use decorators. Since class-based views aren’t functions, decorating them works differently depending on if you’re using or creating a subclass.

Decorating in URLconf¶

You can adjust class-based views by decorating the result of the method. The easiest place to do this is in the URLconf where you deploy your view:

fromdjango.contrib.auth.decoratorsimportlogin_required,permission_requiredfromdjango.views.genericimportTemplateViewfrom.viewsimportVoteViewurlpatterns=[path('about/',login_required(TemplateView.as_view(template_name="secret.html"))),path('vote/',permission_required('polls.can_vote')(VoteView.as_view())),]

This approach applies the decorator on a per-instance basis. If you want every instance of a view to be decorated, you need to take a different approach.

Decorating the class¶

To decorate every instance of a class-based view, you need to decorate the class definition itself. To do this you apply the decorator to the method of the class.

A method on a class isn’t quite the same as a standalone function, so you can’t just apply a function decorator to the method – you need to transform it into a method decorator first. The decorator transforms a function decorator into a method decorator so that it can be used on an instance method. For example:

fromdjango.contrib.auth.decoratorsimportlogin_requiredfromdjango.utils.decoratorsimportmethod_decoratorfromdjango.views.genericimportTemplateViewclassProtectedView(TemplateView):template_name='secret.html'@method_decorator(login_required)defdispatch(self,*args,**kwargs):returnsuper().dispatch(*args,**kwargs)

Or, more succinctly, you can decorate the class instead and pass the name of the method to be decorated as the keyword argument :

@method_decorator(login_required,name='dispatch')classProtectedView(TemplateView):template_name='secret.html'

If you have a set of common decorators used in several places, you can define a list or tuple of decorators and use this instead of invoking multiple times. These two classes are equivalent:

decorators=[never_cache,login_required]@method_decorator(decorators,name='dispatch')classProtectedView(TemplateView):template_name='secret.html'@method_decorator(never_cache,name='dispatch')@method_decorator(login_required,name='dispatch')classProtectedView(TemplateView):template_name='secret.html'

The decorators will process a request in the order they are passed to the decorator. In the example, will process the request before .

In this example, every instance of will have login protection. These examples use , however, the same behavior can be obtained by using .

Note

passes and as parameters to the decorated method on the class. If your method does not accept a compatible set of parameters it will raise a exception.

Sours: https://docs.djangoproject.com/en/3.2/topics/class-based-views/intro/


660 661 662 663 664