summaryrefslogtreecommitdiff
path: root/docs/topics/class-based-views
diff options
context:
space:
mode:
authorTim Graham <timograham@gmail.com>2013-01-01 08:12:42 -0500
committerTim Graham <timograham@gmail.com>2013-01-02 18:50:00 -0500
commitbe1e006c581cc45ed48ae0b423e7a0a996d2199b (patch)
tree5e33669588d7c8d2a49d99f82ae87524d22a9455 /docs/topics/class-based-views
parent61c861546bdbae694f22e2c54e9ca0f42331cae1 (diff)
[1.5.x] Fixed #19516 - Fixed remaining broken links.
Added -n to sphinx builds to catch issues going forward. Backport of 9b5f64cc6e from master.
Diffstat (limited to 'docs/topics/class-based-views')
-rw-r--r--docs/topics/class-based-views/generic-display.txt12
-rw-r--r--docs/topics/class-based-views/generic-editing.txt77
-rw-r--r--docs/topics/class-based-views/mixins.txt192
3 files changed, 150 insertions, 131 deletions
diff --git a/docs/topics/class-based-views/generic-display.txt b/docs/topics/class-based-views/generic-display.txt
index 10279c0f63..dac45c8843 100644
--- a/docs/topics/class-based-views/generic-display.txt
+++ b/docs/topics/class-based-views/generic-display.txt
@@ -257,9 +257,9 @@ Specifying ``model = Publisher`` is really just shorthand for saying
``queryset = Publisher.objects.all()``. However, by using ``queryset``
to define a filtered list of objects you can be more specific about the
objects that will be visible in the view (see :doc:`/topics/db/queries`
-for more information about :class:`QuerySet` objects, and see the
-:doc:`class-based views reference </ref/class-based-views/index>` for the
-complete details).
+for more information about :class:`~django.db.models.query.QuerySet` objects,
+and see the :doc:`class-based views reference </ref/class-based-views/index>`
+for the complete details).
To pick a simple example, we might want to order a list of books by
publication date, with the most recent first::
@@ -312,9 +312,9 @@ what if we wanted to write a view that displayed all the books by some arbitrary
publisher?
Handily, the ``ListView`` has a
-:meth:`~django.views.generic.detail.ListView.get_queryset` method we can
-override. Previously, it has just been returning the value of the ``queryset``
-attribute, but now we can add more logic.
+:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset` method we
+can override. Previously, it has just been returning the value of the
+``queryset`` attribute, but now we can add more logic.
The key part to making this work is that when class-based views are called,
various useful things are stored on ``self``; as well as the request
diff --git a/docs/topics/class-based-views/generic-editing.txt b/docs/topics/class-based-views/generic-editing.txt
index 7d12184705..2f8b8b0711 100644
--- a/docs/topics/class-based-views/generic-editing.txt
+++ b/docs/topics/class-based-views/generic-editing.txt
@@ -7,10 +7,10 @@ Form processing generally has 3 paths:
* POST with invalid data (typically redisplay form with errors)
* POST with valid data (process the data and typically redirect)
-Implementing this yourself often results in a lot of repeated
-boilerplate code (see :ref:`Using a form in a
-view<using-a-form-in-a-view>`). To help avoid this, Django provides a
-collection of generic class-based views for form processing.
+Implementing this yourself often results in a lot of repeated boilerplate code
+(see :ref:`Using a form in a view<using-a-form-in-a-view>`). To help avoid
+this, Django provides a collection of generic class-based views for form
+processing.
Basic Forms
-----------
@@ -28,7 +28,7 @@ Given a simple contact form::
# send email using the self.cleaned_data dictionary
pass
-The view can be constructed using a FormView::
+The view can be constructed using a ``FormView``::
# views.py
from myapp.forms import ContactForm
@@ -50,42 +50,46 @@ Notes:
* FormView inherits
:class:`~django.views.generic.base.TemplateResponseMixin` so
:attr:`~django.views.generic.base.TemplateResponseMixin.template_name`
- can be used here
+ can be used here.
* The default implementation for
- :meth:`~django.views.generic.edit.FormView.form_valid` simply
- redirects to the :attr:`success_url`
+ :meth:`~django.views.generic.edit.FormMixin.form_valid` simply
+ redirects to the :attr:`~django.views.generic.edit.FormMixin.success_url`.
Model Forms
-----------
Generic views really shine when working with models. These generic
-views will automatically create a :class:`ModelForm`, so long as they
-can work out which model class to use:
+views will automatically create a :class:`~django.forms.ModelForm`, so long as
+they can work out which model class to use:
-* If the :attr:`model` attribute is given, that model class will be used
-* If :meth:`get_object()` returns an object, the class of that object
- will be used
-* If a :attr:`queryset` is given, the model for that queryset will be used
+* If the :attr:`~django.views.generic.edit.ModelFormMixin.model` attribute is
+ given, that model class will be used.
+* If :meth:`~django.views.generic.detail.SingleObjectMixin.get_object()`
+ returns an object, the class of that object will be used.
+* If a :attr:`~django.views.generic.detail.SingleObjectMixin.queryset` is
+ given, the model for that queryset will be used.
-Model form views provide a :meth:`form_valid()` implementation that
-saves the model automatically. You can override this if you have any
+Model form views provide a
+:meth:`~django.views.generic.edit.ModelFormMixin.form_valid()` implementation
+that saves the model automatically. You can override this if you have any
special requirements; see below for examples.
-You don't even need to provide a attr:`success_url` for
+You don't even need to provide a ``success_url`` for
:class:`~django.views.generic.edit.CreateView` or
:class:`~django.views.generic.edit.UpdateView` - they will use
-:meth:`get_absolute_url()` on the model object if available.
+:meth:`~django.db.models.Model.get_absolute_url()` on the model object if available.
-If you want to use a custom :class:`ModelForm` (for instance to add
-extra validation) simply set
+If you want to use a custom :class:`~django.forms.ModelForm` (for instance to
+add extra validation) simply set
:attr:`~django.views.generic.edit.FormMixin.form_class` on your view.
.. note::
When specifying a custom form class, you must still specify the model,
- even though the :attr:`form_class` may be a :class:`ModelForm`.
+ even though the :attr:`~django.views.generic.edit.FormMixin.form_class` may
+ be a :class:`~django.forms.ModelForm`.
-First we need to add :meth:`get_absolute_url()` to our :class:`Author`
-class:
+First we need to add :meth:`~django.db.models.Model.get_absolute_url()` to our
+``Author`` class:
.. code-block:: python
@@ -137,8 +141,10 @@ Finally, we hook these new views into the URLconf::
.. note::
- These views inherit :class:`~django.views.generic.detail.SingleObjectTemplateResponseMixin`
- which uses :attr:`~django.views.generic.detail.SingleObjectTemplateResponseMixin.template_name_prefix`
+ These views inherit
+ :class:`~django.views.generic.detail.SingleObjectTemplateResponseMixin`
+ which uses
+ :attr:`~django.views.generic.detail.SingleObjectTemplateResponseMixin.template_name_suffix`
to construct the
:attr:`~django.views.generic.base.TemplateResponseMixin.template_name`
based on the model.
@@ -149,15 +155,17 @@ Finally, we hook these new views into the URLconf::
* :class:`DeleteView` uses ``myapp/author_confirm_delete.html``
If you wish to have separate templates for :class:`CreateView` and
- :class:1UpdateView`, you can set either :attr:`template_name` or
- :attr:`template_name_suffix` on your view class.
+ :class:`UpdateView`, you can set either
+ :attr:`~django.views.generic.base.TemplateResponseMixin.template_name` or
+ :attr:`~django.views.generic.detail.SingleObjectTemplateResponseMixin.template_name_suffix`
+ on your view class.
Models and request.user
-----------------------
To track the user that created an object using a :class:`CreateView`,
-you can use a custom :class:`ModelForm` to do this. First, add the
-foreign key relation to the model::
+you can use a custom :class:`~django.forms.ModelForm` to do this. First, add
+the foreign key relation to the model::
# models.py
from django.contrib.auth import User
@@ -169,7 +177,7 @@ foreign key relation to the model::
# ...
-Create a custom :class:`ModelForm` in order to exclude the
+Create a custom :class:`~django.forms.ModelForm` in order to exclude the
``created_by`` field and prevent the user from editing it:
.. code-block:: python
@@ -183,8 +191,10 @@ Create a custom :class:`ModelForm` in order to exclude the
model = Author
exclude = ('created_by',)
-In the view, use the custom :attr:`form_class` and override
-:meth:`form_valid()` to add the user::
+In the view, use the custom
+:attr:`~django.views.generic.edit.FormMixin.form_class` and override
+:meth:`~django.views.generic.edit.ModelFormMixin.form_valid()` to add the
+user::
# views.py
from django.views.generic.edit import CreateView
@@ -202,7 +212,8 @@ In the view, use the custom :attr:`form_class` and override
Note that you'll need to :ref:`decorate this
view<decorating-class-based-views>` using
:func:`~django.contrib.auth.decorators.login_required`, or
-alternatively handle unauthorised users in the :meth:`form_valid()`.
+alternatively handle unauthorized users in the
+:meth:`~django.views.generic.edit.ModelFormMixin.form_valid()`.
AJAX example
------------
diff --git a/docs/topics/class-based-views/mixins.txt b/docs/topics/class-based-views/mixins.txt
index 923b877cc5..4941ea9755 100644
--- a/docs/topics/class-based-views/mixins.txt
+++ b/docs/topics/class-based-views/mixins.txt
@@ -32,13 +32,14 @@ Two central mixins are provided that help in providing a consistent
interface to working with templates in class-based views.
:class:`~django.views.generic.base.TemplateResponseMixin`
+
Every built in view which returns a
:class:`~django.template.response.TemplateResponse` will call the
:meth:`~django.views.generic.base.TemplateResponseMixin.render_to_response`
- method that :class:`TemplateResponseMixin` provides. Most of the time this
+ method that ``TemplateResponseMixin`` provides. Most of the time this
will be called for you (for instance, it is called by the ``get()`` method
implemented by both :class:`~django.views.generic.base.TemplateView` and
- :class:`~django.views.generic.base.DetailView`); similarly, it's unlikely
+ :class:`~django.views.generic.detail.DetailView`); similarly, it's unlikely
that you'll need to override it, although if you want your response to
return something not rendered via a Django template then you'll want to do
it. For an example of this, see the :ref:`JSONResponseMixin example
@@ -59,10 +60,10 @@ interface to working with templates in class-based views.
:class:`~django.views.generic.base.ContextMixin`
Every built in view which needs context data, such as for rendering a
- template (including :class:`TemplateResponseMixin` above), should call
+ template (including ``TemplateResponseMixin`` above), should call
:meth:`~django.views.generic.base.ContextMixin.get_context_data` passing
any data they want to ensure is in there as keyword arguments.
- ``get_context_data`` returns a dictionary; in :class:`ContextMixin` it
+ ``get_context_data`` returns a dictionary; in ``ContextMixin`` it
simply returns its keyword arguments, but it is common to override this to
add more members to the dictionary.
@@ -106,7 +107,7 @@ URLConf, and looks the object up either from the
:attr:`~django.views.generic.detail.SingleObjectMixin.model` attribute
on the view, or the
:attr:`~django.views.generic.detail.SingleObjectMixin.queryset`
-attribute if that's provided). :class:`SingleObjectMixin` also overrides
+attribute if that's provided). ``SingleObjectMixin`` also overrides
:meth:`~django.views.generic.base.ContextMixin.get_context_data`,
which is used across all Django's built in class-based views to supply
context data for template renders.
@@ -115,10 +116,12 @@ To then make a :class:`~django.template.response.TemplateResponse`,
:class:`DetailView` uses
:class:`~django.views.generic.detail.SingleObjectTemplateResponseMixin`,
which extends :class:`~django.views.generic.base.TemplateResponseMixin`,
-overriding :meth:`get_template_names()` as discussed above. It actually
-provides a fairly sophisticated set of options, but the main one that most
-people are going to use is ``<app_label>/<object_name>_detail.html``. The
-``_detail`` part can be changed by setting
+overriding
+:meth:`~django.views.generic.base.TemplateResponseMixin.get_template_names()`
+as discussed above. It actually provides a fairly sophisticated set of options,
+but the main one that most people are going to use is
+``<app_label>/<object_name>_detail.html``. The ``_detail`` part can be changed
+by setting
:attr:`~django.views.generic.detail.SingleObjectTemplateResponseMixin.template_name_suffix`
on a subclass to something else. (For instance, the :doc:`generic edit
views<generic-editing>` use ``_form`` for create and update views, and
@@ -128,9 +131,10 @@ ListView: working with many Django objects
------------------------------------------
Lists of objects follow roughly the same pattern: we need a (possibly
-paginated) list of objects, typically a :class:`QuerySet`, and then we need
-to make a :class:`TemplateResponse` with a suitable template using
-that list of objects.
+paginated) list of objects, typically a
+:class:`~django.db.models.query.QuerySet`, and then we need to make a
+:class:`~django.template.response.TemplateResponse` with a suitable template
+using that list of objects.
To get the objects, :class:`~django.views.generic.list.ListView` uses
:class:`~django.views.generic.list.MultipleObjectMixin`, which
@@ -138,9 +142,9 @@ provides both
:meth:`~django.views.generic.list.MultipleObjectMixin.get_queryset`
and
:meth:`~django.views.generic.list.MultipleObjectMixin.paginate_queryset`. Unlike
-with :class:`SingleObjectMixin`, there's no need to key off parts of
-the URL to figure out the queryset to work with, so the default just
-uses the
+with :class:`~django.views.generic.detail.SingleObjectMixin`, there's no need
+to key off parts of the URL to figure out the queryset to work with, so the
+default just uses the
:attr:`~django.views.generic.list.MultipleObjectMixin.queryset` or
:attr:`~django.views.generic.list.MultipleObjectMixin.model` attribute
on the view class. A common reason to override
@@ -148,19 +152,19 @@ on the view class. A common reason to override
here would be to dynamically vary the objects, such as depending on
the current user or to exclude posts in the future for a blog.
-:class:`MultipleObjectMixin` also overrides
+:class:`~django.views.generic.list.MultipleObjectMixin` also overrides
:meth:`~django.views.generic.base.ContextMixin.get_context_data` to
include appropriate context variables for pagination (providing
dummies if pagination is disabled). It relies on ``object_list`` being
passed in as a keyword argument, which :class:`ListView` arranges for
it.
-To make a :class:`TemplateResponse`, :class:`ListView` then uses
+To make a :class:`~django.template.response.TemplateResponse`,
+:class:`ListView` then uses
:class:`~django.views.generic.list.MultipleObjectTemplateResponseMixin`;
-as with :class:`SingleObjectTemplateResponseMixin` above, this
-overrides :meth:`get_template_names()` to provide :meth:`a range of
-options
-<~django.views.generic.list.MultipleObjectTempalteResponseMixin>`,
+as with :class:`~django.views.generic.detail.SingleObjectTemplateResponseMixin`
+above, this overrides ``get_template_names()`` to provide :meth:`a range of
+options <django.views.generic.list.MultipleObjectTemplateResponseMixin>`,
with the most commonly-used being
``<app_label>/<object_name>_list.html``, with the ``_list`` part again
being taken from the
@@ -197,13 +201,13 @@ the box.
If in doubt, it's often better to back off and base your work on
:class:`View` or :class:`TemplateView`, perhaps with
- :class:`SimpleObjectMixin` and
- :class:`MultipleObjectMixin`. Although you will probably end up
- writing more code, it is more likely to be clearly understandable
- to someone else coming to it later, and with fewer interactions to
- worry about you will save yourself some thinking. (Of course, you
- can always dip into Django's implementation of the generic class
- based views for inspiration on how to tackle problems.)
+ :class:`~django.views.generic.detail.SingleObjectMixin` and
+ :class:`~django.views.generic.list.MultipleObjectMixin`. Although you
+ will probably end up writing more code, it is more likely to be clearly
+ understandable to someone else coming to it later, and with fewer
+ interactions to worry about you will save yourself some thinking. (Of
+ course, you can always dip into Django's implementation of the generic
+ class based views for inspiration on how to tackle problems.)
.. _method resolution order: http://www.python.org/download/releases/2.3/mro/
@@ -247,9 +251,9 @@ We'll demonstrate this with the publisher modelling we used in the
In practice you'd probably want to record the interest in a key-value
store rather than in a relational database, so we've left that bit
out. The only bit of the view that needs to worry about using
-:class:`SingleObjectMixin` is where we want to look up the author
-we're interested in, which it just does with a simple call to
-``self.get_object()``. Everything else is taken care of for us by the
+:class:`~django.views.generic.detail.SingleObjectMixin` is where we want to
+look up the author we're interested in, which it just does with a simple call
+to ``self.get_object()``. Everything else is taken care of for us by the
mixin.
We can hook this into our URLs easily enough::
@@ -265,7 +269,8 @@ We can hook this into our URLs easily enough::
Note the ``pk`` named group, which
:meth:`~django.views.generic.detail.SingleObjectMixin.get_object` uses
to look up the ``Author`` instance. You could also use a slug, or
-any of the other features of :class:`SingleObjectMixin`.
+any of the other features of
+:class:`~django.views.generic.detail.SingleObjectMixin`.
Using SingleObjectMixin with ListView
-------------------------------------
@@ -277,23 +282,24 @@ example, you might want to paginate through all the books by a
particular publisher.
One way to do this is to combine :class:`ListView` with
-:class:`SingleObjectMixin`, so that the queryset for the paginated
-list of books can hang off the publisher found as the single
+:class:`~django.views.generic.detail.SingleObjectMixin`, so that the queryset
+for the paginated list of books can hang off the publisher found as the single
object. In order to do this, we need to have two different querysets:
**Publisher queryset for use in get_object**
- We'll set that up directly when we call :meth:`get_object()`.
+ We'll set that up directly when we call ``get_object()``.
**Book queryset for use by ListView**
- We'll figure that out ourselves in :meth:`get_queryset()` so we
- can take into account the Publisher we're looking at.
+ We'll figure that out ourselves in ``get_queryset()`` so we
+ can take into account the ``Publisher`` we're looking at.
.. note::
- We have to think carefully about :meth:`get_context_data()`.
- Since both :class:`SingleObjectMixin` and :class:`ListView` will
+ We have to think carefully about ``get_context_data()``.
+ Since both :class:`~django.views.generic.detail.SingleObjectMixin` and
+ :class:`ListView` will
put things in the context data under the value of
- :attr:`context_object_name` if it's set, we'll instead explictly
+ ``context_object_name`` if it's set, we'll instead explictly
ensure the Publisher is in the context data. :class:`ListView`
will add in the suitable ``page_obj`` and ``paginator`` for us
providing we remember to call ``super()``.
@@ -316,13 +322,14 @@ Now we can write a new ``PublisherDetail``::
self.object = self.get_object(Publisher.objects.all())
return self.object.book_set.all()
-Notice how we set ``self.object`` within :meth:`get_queryset` so we
-can use it again later in :meth:`get_context_data`. If you don't set
-:attr:`template_name`, the template will default to the normal
+Notice how we set ``self.object`` within ``get_queryset()`` so we
+can use it again later in ``get_context_data()``. If you don't set
+``template_name``, the template will default to the normal
:class:`ListView` choice, which in this case would be
``"books/book_list.html"`` because it's a list of books;
-:class:`ListView` knows nothing about :class:`SingleObjectMixin`, so
-it doesn't have any clue this view is anything to do with a Publisher.
+:class:`ListView` knows nothing about
+:class:`~django.views.generic.detail.SingleObjectMixin`, so it doesn't have
+any clue this view is anything to do with a Publisher.
.. highlightlang:: html+django
@@ -365,7 +372,7 @@ Generally you can use
:class:`~django.views.generic.base.TemplateResponseMixin` and
:class:`~django.views.generic.detail.SingleObjectMixin` when you need
their functionality. As shown above, with a bit of care you can even
-combine :class:`SingleObjectMixin` with
+combine ``SingleObjectMixin`` with
:class:`~django.views.generic.list.ListView`. However things get
increasingly complex as you try to do so, and a good rule of thumb is:
@@ -376,48 +383,48 @@ increasingly complex as you try to do so, and a good rule of thumb is:
list<generic-display>`, :doc:`editing<generic-editing>` and
date. For example it's fine to combine
:class:`TemplateView` (built in view) with
- :class:`MultipleObjectMixin` (generic list), but you're likely to
- have problems combining :class:`SingleObjectMixin` (generic
- detail) with :class:`MultipleObjectMixin` (generic list).
+ :class:`~django.views.generic.list.MultipleObjectMixin` (generic list), but
+ you're likely to have problems combining ``SingleObjectMixin`` (generic
+ detail) with ``MultipleObjectMixin`` (generic list).
To show what happens when you try to get more sophisticated, we show
an example that sacrifices readability and maintainability when there
is a simpler solution. First, let's look at a naive attempt to combine
:class:`~django.views.generic.detail.DetailView` with
:class:`~django.views.generic.edit.FormMixin` to enable use to
-``POST`` a Django :class:`Form` to the same URL as we're displaying an
-object using :class:`DetailView`.
+``POST`` a Django :class:`~django.forms.Form` to the same URL as we're
+displaying an object using :class:`DetailView`.
Using FormMixin with DetailView
-------------------------------
Think back to our earlier example of using :class:`View` and
-:class:`SingleObjectMixin` together. We were recording a user's
-interest in a particular author; say now that we want to let them
-leave a message saying why they like them. Again, let's assume we're
+:class:`~django.views.generic.detail.SingleObjectMixin` together. We were
+recording a user's interest in a particular author; say now that we want to
+let them leave a message saying why they like them. Again, let's assume we're
not going to store this in a relational database but instead in
something more esoteric that we won't worry about here.
-At this point it's natural to reach for a :class:`Form` to encapsulate
-the information sent from the user's browser to Django. Say also that
-we're heavily invested in `REST`_, so we want to use the same URL for
+At this point it's natural to reach for a :class:`~django.forms.Form` to
+encapsulate the information sent from the user's browser to Django. Say also
+that we're heavily invested in `REST`_, so we want to use the same URL for
displaying the author as for capturing the message from the
user. Let's rewrite our ``AuthorDetailView`` to do that.
.. _REST: http://en.wikipedia.org/wiki/Representational_state_transfer
We'll keep the ``GET`` handling from :class:`DetailView`, although
-we'll have to add a :class:`Form` into the context data so we can
+we'll have to add a :class:`~django.forms.Form` into the context data so we can
render it in the template. We'll also want to pull in form processing
from :class:`~django.views.generic.edit.FormMixin`, and write a bit of
code so that on ``POST`` the form gets called appropriately.
.. note::
- We use :class:`FormMixin` and implement :meth:`post()` ourselves
- rather than try to mix :class:`DetailView` with :class:`FormView`
- (which provides a suitable :meth:`post()` already) because both of
- the views implement :meth:`get()`, and things would get much more
+ We use :class:`~django.views.generic.edit.FormMixin` and implement
+ ``post()`` ourselves rather than try to mix :class:`DetailView` with
+ :class:`FormView` (which provides a suitable ``post()`` already) because
+ both of the views implement ``get()``, and things would get much more
confusing.
.. highlightlang:: python
@@ -472,24 +479,24 @@ Our new ``AuthorDetail`` looks like this::
# record the interest using the message in form.cleaned_data
return super(AuthorDetail, self).form_valid(form)
-:meth:`get_success_url()` is just providing somewhere to redirect to,
+``get_success_url()`` is just providing somewhere to redirect to,
which gets used in the default implementation of
-:meth:`form_valid()`. We have to provide our own :meth:`post()` as
-noted earlier, and override :meth:`get_context_data()` to make the
-:class:`Form` available in the context data.
+``form_valid()``. We have to provide our own ``post()`` as
+noted earlier, and override ``get_context_data()`` to make the
+:class:`~django.forms.Form` available in the context data.
A better solution
-----------------
It should be obvious that the number of subtle interactions between
-:class:`FormMixin` and :class:`DetailView` is already testing our
-ability to manage things. It's unlikely you'd want to write this kind
-of class yourself.
+:class:`~django.views.generic.edit.FormMixin` and :class:`DetailView` is
+already testing our ability to manage things. It's unlikely you'd want to
+write this kind of class yourself.
-In this case, it would be fairly easy to just write the :meth:`post()`
+In this case, it would be fairly easy to just write the ``post()``
method yourself, keeping :class:`DetailView` as the only generic
-functionality, although writing :class:`Form` handling code involves a
-lot of duplication.
+functionality, although writing :class:`~django.forms.Form` handling code
+involves a lot of duplication.
Alternatively, it would still be easier than the above approach to
have a separate view for processing the form, which could use
@@ -502,15 +509,15 @@ An alternative better solution
What we're really trying to do here is to use two different class
based views from the same URL. So why not do just that? We have a very
clear division here: ``GET`` requests should get the
-:class:`DetailView` (with the :class:`Form` added to the context
+:class:`DetailView` (with the :class:`~django.forms.Form` added to the context
data), and ``POST`` requests should get the :class:`FormView`. Let's
set up those views first.
The ``AuthorDisplay`` view is almost the same as :ref:`when we
first introduced AuthorDetail<generic-views-extra-work>`; we have to
-write our own :meth:`get_context_data()` to make the
+write our own ``get_context_data()`` to make the
``AuthorInterestForm`` available to the template. We'll skip the
-:meth:`get_object()` override from before for clarity.
+``get_object()`` override from before for clarity.
.. code-block:: python
@@ -533,9 +540,9 @@ write our own :meth:`get_context_data()` to make the
return super(AuthorDisplay, self).get_context_data(**context)
Then the ``AuthorInterest`` is a simple :class:`FormView`, but we
-have to bring in :class:`SingleObjectMixin` so we can find the author
-we're talking about, and we have to remember to set
-:attr:`template_name` to ensure that form errors will render the same
+have to bring in :class:`~django.views.generic.detail.SingleObjectMixin` so we
+can find the author we're talking about, and we have to remember to set
+``template_name`` to ensure that form errors will render the same
template as ``AuthorDisplay`` is using on ``GET``.
.. code-block:: python
@@ -568,14 +575,14 @@ template as ``AuthorDisplay`` is using on ``GET``.
return super(AuthorInterest, self).form_valid(form)
Finally we bring this together in a new ``AuthorDetail`` view. We
-already know that calling :meth:`as_view()` on a class-based view
-gives us something that behaves exactly like a function based view, so
-we can do that at the point we choose between the two subviews.
+already know that calling :meth:`~django.views.generic.base.View.as_view()` on
+a class-based view gives us something that behaves exactly like a function
+based view, so we can do that at the point we choose between the two subviews.
-You can of course pass through keyword arguments to :meth:`as_view()`
-in the same way you would in your URLconf, such as if you wanted the
-``AuthorInterest`` behaviour to also appear at another URL but
-using a different template.
+You can of course pass through keyword arguments to
+:meth:`~django.views.generic.base.View.as_view()` in the same way you
+would in your URLconf, such as if you wanted the ``AuthorInterest`` behavior
+to also appear at another URL but using a different template.
.. code-block:: python
@@ -646,8 +653,8 @@ Now we mix this into the base TemplateView::
Equally we could use our mixin with one of the generic views. We can make our
own version of :class:`~django.views.generic.detail.DetailView` by mixing
-:class:`JSONResponseMixin` with the
-:class:`~django.views.generic.detail.BaseDetailView` -- (the
+``JSONResponseMixin`` with the
+``django.views.generic.detail.BaseDetailView`` -- (the
:class:`~django.views.generic.detail.DetailView` before template
rendering behavior has been mixed in)::
@@ -662,11 +669,12 @@ If you want to be really adventurous, you could even mix a
:class:`~django.views.generic.detail.DetailView` subclass that is able
to return *both* HTML and JSON content, depending on some property of
the HTTP request, such as a query argument or a HTTP header. Just mix
-in both the :class:`JSONResponseMixin` and a
+in both the ``JSONResponseMixin`` and a
:class:`~django.views.generic.detail.SingleObjectTemplateResponseMixin`,
-and override the implementation of :func:`render_to_response()` to defer
-to the appropriate subclass depending on the type of response that the user
-requested::
+and override the implementation of
+:func:`~django.views.generic.base.TemplateResponseMixin.render_to_response()`
+to defer to the appropriate subclass depending on the type of response that the
+user requested::
class HybridDetailView(JSONResponseMixin, SingleObjectTemplateResponseMixin, BaseDetailView):
def render_to_response(self, context):
@@ -678,5 +686,5 @@ requested::
Because of the way that Python resolves method overloading, the local
``render_to_response()`` implementation will override the versions provided by
-:class:`JSONResponseMixin` and
+``JSONResponseMixin`` and
:class:`~django.views.generic.detail.SingleObjectTemplateResponseMixin`.