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...
1 parent 1a10a06 commit c4c7fbcc0d9264beb931b45969fc0d8d655c4f83 @jezdez jezdez committed Jun 11, 2012
Showing with 3,112 additions and 2,016 deletions.
  1. +5 −0 AUTHORS
  2. +8 −1 django/views/generic/base.py
  3. +13 −1 django/views/generic/dates.py
  4. +14 −2 django/views/generic/detail.py
  5. +35 −4 django/views/generic/edit.py
  6. +9 −0 django/views/generic/list.py
  7. +1 −1 docs/glossary.txt
  8. +1 −1 docs/howto/static-files.txt
  9. +4 −3 docs/index.txt
  10. +2 −2 docs/internals/deprecation.txt
  11. +1 −1 docs/intro/tutorial04.txt
  12. +1 −1 docs/misc/api-stability.txt
  13. +0 −1,367 docs/ref/class-based-views.txt
  14. +224 −0 docs/ref/class-based-views/base.txt
  15. +273 −0 docs/ref/class-based-views/generic-date-based.txt
  16. +86 −0 docs/ref/class-based-views/generic-display.txt
  17. +78 −0 docs/ref/class-based-views/generic-editing.txt
  18. +59 −0 docs/ref/class-based-views/index.txt
  19. +256 −0 docs/ref/class-based-views/mixins-date-based.txt
  20. +183 −0 docs/ref/class-based-views/mixins-editing.txt
  21. +175 −0 docs/ref/class-based-views/mixins-multiple-object.txt
  22. +60 −0 docs/ref/class-based-views/mixins-simple.txt
  23. +124 −0 docs/ref/class-based-views/mixins-single-object.txt
  24. +14 −0 docs/ref/class-based-views/mixins.txt
  25. +1 −1 docs/ref/index.txt
  26. +1 −1 docs/releases/1.3-alpha-1.txt
  27. +1 −1 docs/releases/1.3.txt
  28. +4 −3 docs/topics/auth.txt
  29. +0 −624 docs/topics/class-based-views.txt
  30. +432 −0 docs/topics/class-based-views/generic-display.txt
  31. +205 −0 docs/topics/class-based-views/generic-editing.txt
  32. +233 −0 docs/topics/class-based-views/index.txt
  33. +605 −0 docs/topics/class-based-views/mixins.txt
  34. +2 −0 docs/topics/forms/index.txt
  35. +1 −1 docs/topics/http/generic-views.txt
  36. +1 −1 docs/topics/index.txt
View
@@ -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):
View
@@ -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`.
View
@@ -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>`.
Oops, something went wrong.

2 comments on commit c4c7fbc

@kennethreitz

❤️

@sindresorhus

❤️

Please sign in to comment.