2012-06-11 08:34:00 +00:00
|
|
|
=================
|
|
|
|
Class-based views
|
|
|
|
=================
|
|
|
|
|
|
|
|
A view is a callable which takes a request and returns a
|
|
|
|
response. This can be more than just a function, and Django provides
|
|
|
|
an example of some classes which can be used as views. These allow you
|
|
|
|
to structure your views and reuse code by harnessing inheritance and
|
|
|
|
mixins. There are also some generic views for simple tasks which we'll
|
|
|
|
get to later, but you may want to design your own structure of
|
|
|
|
reusable views which suits your use case. For full details, see the
|
2012-08-25 12:11:56 +00:00
|
|
|
:doc:`class-based views reference documentation</ref/class-based-views/index>`.
|
2012-06-11 08:34:00 +00:00
|
|
|
|
|
|
|
.. toctree::
|
|
|
|
:maxdepth: 1
|
|
|
|
|
2013-02-27 12:12:37 +00:00
|
|
|
intro
|
2012-06-11 08:34:00 +00:00
|
|
|
generic-display
|
|
|
|
generic-editing
|
|
|
|
mixins
|
|
|
|
|
|
|
|
Basic examples
|
|
|
|
==============
|
|
|
|
|
|
|
|
Django provides base view classes which will suit a wide range of applications.
|
|
|
|
All views inherit from the :class:`~django.views.generic.base.View` class, which
|
|
|
|
handles linking the view in to the URLs, HTTP method dispatching and other
|
2012-11-22 00:06:17 +00:00
|
|
|
simple features. :class:`~django.views.generic.base.RedirectView` is for a
|
|
|
|
simple HTTP redirect, and :class:`~django.views.generic.base.TemplateView`
|
|
|
|
extends the base class to make it also render a template.
|
2012-06-11 08:34:00 +00:00
|
|
|
|
|
|
|
|
2012-08-25 12:11:56 +00:00
|
|
|
Simple usage in your URLconf
|
|
|
|
============================
|
2012-06-11 08:34:00 +00:00
|
|
|
|
2012-08-25 12:11:56 +00:00
|
|
|
The simplest way to use generic views is to create them directly in your
|
|
|
|
URLconf. If you're only changing a few simple attributes on a class-based view,
|
2012-11-22 00:06:17 +00:00
|
|
|
you can simply pass them into the
|
|
|
|
:meth:`~django.views.generic.base.View.as_view` method call itself::
|
2012-06-11 08:34:00 +00:00
|
|
|
|
2016-10-20 17:29:04 +00:00
|
|
|
from django.urls import path
|
2012-06-11 08:34:00 +00:00
|
|
|
from django.views.generic import TemplateView
|
|
|
|
|
2014-04-02 00:46:34 +00:00
|
|
|
urlpatterns = [
|
2016-10-20 17:29:04 +00:00
|
|
|
path('about/', TemplateView.as_view(template_name="about.html")),
|
2014-04-02 00:46:34 +00:00
|
|
|
]
|
2012-06-11 08:34:00 +00:00
|
|
|
|
2012-11-22 00:06:17 +00:00
|
|
|
Any arguments passed to :meth:`~django.views.generic.base.View.as_view` will
|
|
|
|
override attributes set on the class. In this example, we set ``template_name``
|
|
|
|
on the ``TemplateView``. A similar overriding pattern can be used for the
|
|
|
|
``url`` attribute on :class:`~django.views.generic.base.RedirectView`.
|
2012-06-11 08:34:00 +00:00
|
|
|
|
|
|
|
|
2012-08-25 12:11:56 +00:00
|
|
|
Subclassing generic views
|
|
|
|
=========================
|
2012-06-11 08:34:00 +00:00
|
|
|
|
2012-08-25 12:11:56 +00:00
|
|
|
The second, more powerful way to use generic views is to inherit from an
|
|
|
|
existing view and override attributes (such as the ``template_name``) or
|
|
|
|
methods (such as ``get_context_data``) in your subclass to provide new values
|
|
|
|
or methods. Consider, for example, a view that just displays one template,
|
|
|
|
``about.html``. Django has a generic view to do this -
|
|
|
|
:class:`~django.views.generic.base.TemplateView` - so we can just subclass it,
|
|
|
|
and override the template name::
|
2012-06-11 08:34:00 +00:00
|
|
|
|
2012-08-25 12:11:56 +00:00
|
|
|
# some_app/views.py
|
|
|
|
from django.views.generic import TemplateView
|
2012-06-11 08:34:00 +00:00
|
|
|
|
2012-08-25 12:11:56 +00:00
|
|
|
class AboutView(TemplateView):
|
|
|
|
template_name = "about.html"
|
2012-06-11 08:34:00 +00:00
|
|
|
|
2012-08-25 12:11:56 +00:00
|
|
|
Then we just need to add this new view into our URLconf.
|
2013-10-14 11:59:56 +00:00
|
|
|
:class:`~django.views.generic.base.TemplateView` is a class, not a function,
|
|
|
|
so we point the URL to the :meth:`~django.views.generic.base.View.as_view`
|
|
|
|
class method instead, which provides a function-like entry to class-based
|
|
|
|
views::
|
2012-06-11 08:34:00 +00:00
|
|
|
|
2012-08-25 12:11:56 +00:00
|
|
|
# urls.py
|
2016-10-20 17:29:04 +00:00
|
|
|
from django.urls import path
|
2012-08-25 12:11:56 +00:00
|
|
|
from some_app.views import AboutView
|
2012-06-11 08:34:00 +00:00
|
|
|
|
2014-04-02 00:46:34 +00:00
|
|
|
urlpatterns = [
|
2016-10-20 17:29:04 +00:00
|
|
|
path('about/', AboutView.as_view()),
|
2014-04-02 00:46:34 +00:00
|
|
|
]
|
2012-06-11 08:34:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
For more information on how to use the built in generic views, consult the next
|
2015-08-18 20:01:36 +00:00
|
|
|
topic on :doc:`generic class-based views</topics/class-based-views/generic-display>`.
|
2012-06-11 08:34:00 +00:00
|
|
|
|
2012-09-08 22:45:02 +00:00
|
|
|
.. _supporting-other-http-methods:
|
|
|
|
|
|
|
|
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::
|
|
|
|
|
2016-10-20 17:29:04 +00:00
|
|
|
from django.urls import path
|
2012-09-08 22:45:02 +00:00
|
|
|
from books.views import BookListView
|
|
|
|
|
2014-04-02 00:46:34 +00:00
|
|
|
urlpatterns = [
|
2016-10-20 17:29:04 +00:00
|
|
|
path('books/', BookListView.as_view()),
|
2014-04-02 00:46:34 +00:00
|
|
|
]
|
2012-09-08 22:45:02 +00:00
|
|
|
|
|
|
|
And the view::
|
|
|
|
|
|
|
|
from django.http import HttpResponse
|
|
|
|
from django.views.generic import ListView
|
|
|
|
from books.models import Book
|
|
|
|
|
|
|
|
class BookListView(ListView):
|
|
|
|
model = Book
|
|
|
|
|
|
|
|
def head(self, *args, **kwargs):
|
|
|
|
last_book = self.get_queryset().latest('publication_date')
|
2019-02-09 21:27:32 +00:00
|
|
|
response = HttpResponse()
|
2012-09-08 22:45:02 +00:00
|
|
|
# RFC 1123 date format
|
|
|
|
response['Last-Modified'] = last_book.publication_date.strftime('%a, %d %b %Y %H:%M:%S GMT')
|
|
|
|
return response
|
|
|
|
|
|
|
|
If the view is accessed from a ``GET`` request, a plain-and-simple object
|
|
|
|
list is returned in the response (using ``book_list.html`` template). But if
|
|
|
|
the client issues a ``HEAD`` request, the response has an empty body and
|
|
|
|
the ``Last-Modified`` header indicates when the most recent book was published.
|
|
|
|
Based on this information, the client may or may not download the full object
|
|
|
|
list.
|