Skip to content
Permalink
Browse files
Fixed #18451 -- Vastly improved class based view documentation.
Many thanks to Daniel Greenfeld, James Aylett, Marc Tamlyn, Simon Williams, Danilo Bargen and Luke Plant for their work on this.
  • Loading branch information
jezdez committed Jun 11, 2012
1 parent 1a10a06 commit c4c7fbcc0d9264beb931b45969fc0d8d655c4f83
Show file tree
Hide file tree
Showing 36 changed files with 3,112 additions and 2,016 deletions.
@@ -51,6 +51,7 @@ answer newbie questions, and generally made Django that much better:
Antoni Aloy
Daniel Alves Barbosa de Oliveira Vaz <danielvaz@gmail.com>
AgarFu <heaven@croasanaso.sytes.net>
James Aylett
Dagur Páll Ammendrup <dagurp@gmail.com>
Collin Anderson <cmawebsite@gmail.com>
Jeff Anderson <jefferya@programmerq.net>
@@ -85,6 +86,7 @@ answer newbie questions, and generally made Django that much better:
Esdras Beleza <linux@esdrasbeleza.com>
Chris Bennett <chrisrbennett@yahoo.com>
James Bennett
Danilo Bargen
Shai Berger <shai@platonix.com>
Julian Bez
Arvis Bickovskis <viestards.lists@gmail.com>
@@ -222,6 +224,7 @@ answer newbie questions, and generally made Django that much better:
pradeep.gowda@gmail.com
Collin Grady <collin@collingrady.com>
Gabriel Grant <g@briel.ca>
Daniel Greenfeld
Simon Greenhill <dev@simon.net.nz>
Owen Griffiths
Espen Grindhaug <http://grindhaug.org/>
@@ -507,6 +510,7 @@ answer newbie questions, and generally made Django that much better:
Aaron Swartz <http://www.aaronsw.com/>
Ville Säävuori <http://www.unessa.net/>
Mart Sõmermaa <http://mrts.pri.ee/>
Marc Tamlyn
Christian Tanzer <tanzer@swing.co.at>
Tyler Tarabula <tyler.tarabula@gmail.com>
Tyson Tate <tyson@fallingbullets.com>
@@ -555,6 +559,7 @@ answer newbie questions, and generally made Django that much better:
Mike Wiacek <mjwiacek@google.com>
Frank Wierzbicki
charly.wilhelm@gmail.com
Simon Williams
Derek Willis <http://blog.thescoop.org/>
Rachel Willmer <http://www.willmer.com/kb/>
Jakub Wilk <ubanus@users.sf.net>
@@ -90,6 +90,9 @@ def http_method_not_allowed(self, request, *args, **kwargs):
return http.HttpResponseNotAllowed(self._allowed_methods())

def options(self, request, *args, **kwargs):
"""
Handles responding to requests for the OPTIONS HTTP verb.
"""
response = http.HttpResponse()
response['Allow'] = ', '.join(self._allowed_methods())
response['Content-Length'] = 0
@@ -108,7 +111,11 @@ class TemplateResponseMixin(object):

def render_to_response(self, context, **response_kwargs):
"""
Returns a response with a template rendered with the given context.
Returns a response, using the `response_class` for this
view, with a template rendered with the given context.
If any keyword arguments are provided, they will be
passed to the constructor of the response class.
"""
return self.response_class(
request = self.request,
@@ -14,6 +14,9 @@
from django.views.generic.list import MultipleObjectMixin, MultipleObjectTemplateResponseMixin

class YearMixin(object):
"""
Mixin for views manipulating year-based data.
"""
year_format = '%Y'
year = None

@@ -67,6 +70,9 @@ def _get_current_year(self, date):


class MonthMixin(object):
"""
Mixin for views manipulating month-based data.
"""
month_format = '%b'
month = None

@@ -123,6 +129,9 @@ def _get_current_month(self, date):


class DayMixin(object):
"""
Mixin for views manipulating day-based data.
"""
day_format = '%d'
day = None

@@ -176,6 +185,9 @@ def _get_current_day(self, date):


class WeekMixin(object):
"""
Mixin for views manipulating week-based data.
"""
week_format = '%U'
week = None

@@ -312,7 +324,7 @@ def _make_single_date_lookup(self, date):

class BaseDateListView(MultipleObjectMixin, DateMixin, View):
"""
Abstract base class for date-based views display a list of objects.
Abstract base class for date-based views displaying a list of objects.
"""
allow_empty = False

@@ -48,6 +48,7 @@ def get_object(self, queryset=None):
% self.__class__.__name__)

try:
# Get the single item from the filtered queryset
obj = queryset.get()
except ObjectDoesNotExist:
raise Http404(_("No %(verbose_name)s found matching the query") %
@@ -88,6 +89,9 @@ def get_context_object_name(self, obj):
return None

def get_context_data(self, **kwargs):
"""
Insert the single object into the context dict.
"""
context = {}
context_object_name = self.get_context_object_name(self.object)
if context_object_name:
@@ -97,6 +101,9 @@ def get_context_data(self, **kwargs):


class BaseDetailView(SingleObjectMixin, View):
"""
A base view for displaying a single object
"""
def get(self, request, *args, **kwargs):
self.object = self.get_object()
context = self.get_context_data(object=self.object)
@@ -109,8 +116,13 @@ class SingleObjectTemplateResponseMixin(TemplateResponseMixin):

def get_template_names(self):
"""
Return a list of template names to be used for the request. Must return
a list. May not be called if render_to_response is overridden.
Return a list of template names to be used for the request. May not be
called if render_to_response is overridden. Returns the following list:
* the value of ``template_name`` on the view (if provided)
* the contents of the ``template_name_field`` field on the
object instance that the view is operating upon (if available)
* ``<app_label>/<object_name><template_name_suffix>.html``
"""
try:
names = super(SingleObjectTemplateResponseMixin, self).get_template_names()
@@ -46,6 +46,9 @@ def get_form_kwargs(self):
return kwargs

def get_success_url(self):
"""
Returns the supplied success URL.
"""
if self.success_url:
url = self.success_url
else:
@@ -54,9 +57,16 @@ def get_success_url(self):
return url

def form_valid(self, form):
"""
If the form is valid, redirect to the supplied URL.
"""
return HttpResponseRedirect(self.get_success_url())

def form_invalid(self, form):
"""
If the form is invalid, re-render the context data with the
data-filled form and errors.
"""
return self.render_to_response(self.get_context_data(form=form))


@@ -67,7 +77,7 @@ class ModelFormMixin(FormMixin, SingleObjectMixin):

def get_form_class(self):
"""
Returns the form class to use in this view
Returns the form class to use in this view.
"""
if self.form_class:
return self.form_class
@@ -94,6 +104,9 @@ def get_form_kwargs(self):
return kwargs

def get_success_url(self):
"""
Returns the supplied URL.
"""
if self.success_url:
url = self.success_url % self.object.__dict__
else:
@@ -106,10 +119,17 @@ def get_success_url(self):
return url

def form_valid(self, form):
"""
If the form is valid, save the associated model.
"""
self.object = form.save()
return super(ModelFormMixin, self).form_valid(form)

def get_context_data(self, **kwargs):
"""
If an object has been supplied, inject it into the context with the
supplied context_object_name name.
"""
context = {}
if self.object:
context['object'] = self.object
@@ -122,14 +142,21 @@ def get_context_data(self, **kwargs):

class ProcessFormView(View):
"""
A mixin that processes a form on POST.
A mixin that renders a form on GET and processes it on POST.
"""
def get(self, request, *args, **kwargs):
"""
Handles GET requests and instantiates a blank version of the form.
"""
form_class = self.get_form_class()
form = self.get_form(form_class)
return self.render_to_response(self.get_context_data(form=form))

def post(self, request, *args, **kwargs):
"""
Handles POST requests, instantiating a form instance with the passed
POST variables and then checked for validity.
"""
form_class = self.get_form_class()
form = self.get_form(form_class)
if form.is_valid():
@@ -172,7 +199,7 @@ def post(self, request, *args, **kwargs):

class CreateView(SingleObjectTemplateResponseMixin, BaseCreateView):
"""
View for creating an new object instance,
View for creating a new object instance,
with a response rendered by template.
"""
template_name_suffix = '_form'
@@ -196,7 +223,7 @@ def post(self, request, *args, **kwargs):
class UpdateView(SingleObjectTemplateResponseMixin, BaseUpdateView):
"""
View for updating an object,
with a response rendered by template..
with a response rendered by template.
"""
template_name_suffix = '_form'

@@ -208,6 +235,10 @@ class DeletionMixin(object):
success_url = None

def delete(self, request, *args, **kwargs):
"""
Calls the delete() method on the fetched object and then
redirects to the success URL.
"""
self.object = self.get_object()
self.object.delete()
return HttpResponseRedirect(self.get_success_url())
@@ -8,6 +8,9 @@


class MultipleObjectMixin(ContextMixin):
"""
A mixin for views manipulating multiple objects.
"""
allow_empty = True
queryset = None
model = None
@@ -111,6 +114,9 @@ def get_context_data(self, **kwargs):


class BaseListView(MultipleObjectMixin, View):
"""
A base view for displaying a list of objects.
"""
def get(self, request, *args, **kwargs):
self.object_list = self.get_queryset()
allow_empty = self.get_allow_empty()
@@ -132,6 +138,9 @@ def get(self, request, *args, **kwargs):


class MultipleObjectTemplateResponseMixin(TemplateResponseMixin):
"""
Mixin for responding with a template and list of objects.
"""
template_name_suffix = '_list'

def get_template_names(self):
@@ -16,7 +16,7 @@ Glossary
A higher-order :term:`view` function that provides an abstract/generic
implementation of a common idiom or pattern found in view development.

See :doc:`/ref/class-based-views`.
See :doc:`/topics/class-based-views/index`.

model
Models store your application's data.
@@ -175,7 +175,7 @@ using :class:`~django.template.RequestContext` when rendering the template.
As a brief refresher, context processors add variables into the contexts of
every template. However, context processors require that you use
:class:`~django.template.RequestContext` when rendering templates. This happens
automatically if you're using a :doc:`generic view </ref/class-based-views>`,
automatically if you're using a :doc:`generic view </ref/class-based-views/index>`,
but in views written by hand you'll need to explicitly use ``RequestContext``
To see how that works, and to read more details, check out
:ref:`subclassing-context-requestcontext`.
@@ -105,9 +105,10 @@ The view layer
:doc:`Managing files <topics/files>` |
:doc:`Custom storage <howto/custom-file-storage>`

* **Generic views:**
:doc:`Overview<topics/class-based-views>` |
:doc:`Built-in generic views<ref/class-based-views>`
* **Class-based views:**
:doc:`Overview<topics/class-based-views/index>` |
:doc:`Built-in class-based views<ref/class-based-views/index>` |
:doc:`Built-in view mixins<ref/class-based-views/mixins>`

* **Advanced:**
:doc:`Generating CSV <howto/outputting-csv>` |
@@ -134,7 +134,7 @@ these changes.

* The function-based generic view modules will be removed in favor of their
class-based equivalents, outlined :doc:`here
</topics/class-based-views>`:
</topics/class-based-views/index>`:

* The :class:`~django.core.servers.basehttp.AdminMediaHandler` will be
removed. In its place use
@@ -221,7 +221,7 @@ these changes.
the 1.4 release. They will be removed.

* The :doc:`form wizard </ref/contrib/formtools/form-wizard>` has been
refactored to use class based views with pluggable backends in 1.4.
refactored to use class-based views with pluggable backends in 1.4.
The previous implementation will be removed.

* Legacy ways of calling
@@ -320,7 +320,7 @@ function anymore -- generic views can be (and are) used multiple times
Run the server, and use your new polling app based on generic views.

For full details on generic views, see the :doc:`generic views documentation
</topics/class-based-views>`.
</topics/class-based-views/index>`.

Coming soon
===========
@@ -54,7 +54,7 @@ of 1.0. This includes these APIs:
- :doc:`HTTP request/response handling </topics/http/index>`, including file
uploads, middleware, sessions, URL resolution, view, and shortcut APIs.

- :doc:`Generic views </topics/class-based-views>`.
- :doc:`Generic views </topics/class-based-views/index>`.

- :doc:`Internationalization </topics/i18n/index>`.

2 comments on commit c4c7fbc

@kennethreitz
Copy link

@kennethreitz kennethreitz commented on c4c7fbc Jun 11, 2012

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

@sindresorhus
Copy link

@sindresorhus sindresorhus commented on c4c7fbc Jun 11, 2012

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

Please sign in to comment.