Author: russellm
Date: 2010-11-19 23:10:13 -0600 (Fri, 19 Nov 2010)
New Revision: 14642

Modified:
   django/trunk/django/utils/decorators.py
   django/trunk/django/views/generic/base.py
   django/trunk/docs/topics/class-based-views.txt
Log:
Fixed #14512 -- Added documentation on how to apply decorators to class-based 
generic views. Thanks to ?\197?\129ukasz Rekucki for his work on the issue.

Modified: django/trunk/django/utils/decorators.py
===================================================================
--- django/trunk/django/utils/decorators.py     2010-11-20 01:56:34 UTC (rev 
14641)
+++ django/trunk/django/utils/decorators.py     2010-11-20 05:10:13 UTC (rev 
14642)
@@ -1,11 +1,15 @@
 "Functions that help with dynamically creating decorators for views."
 
-import types
 try:
     from functools import wraps, update_wrapper, WRAPPER_ASSIGNMENTS
 except ImportError:
     from django.utils.functional import wraps, update_wrapper, 
WRAPPER_ASSIGNMENTS  # Python 2.4 fallback.
 
+class classonlymethod(classmethod):
+    def __get__(self, instance, owner):
+        if instance is not None:
+            raise AttributeError("This method is available only on the view 
class.")
+        return super(classonlymethod, self).__get__(instance, owner)
 
 def method_decorator(decorator):
     """

Modified: django/trunk/django/views/generic/base.py
===================================================================
--- django/trunk/django/views/generic/base.py   2010-11-20 01:56:34 UTC (rev 
14641)
+++ django/trunk/django/views/generic/base.py   2010-11-20 05:10:13 UTC (rev 
14642)
@@ -1,19 +1,12 @@
-import copy
 from django import http
 from django.core.exceptions import ImproperlyConfigured
 from django.template import RequestContext, loader
-from django.utils.translation import ugettext_lazy as _
 from django.utils.functional import update_wrapper
 from django.utils.log import getLogger
+from django.utils.decorators import classonlymethod
 
 logger = getLogger('django.request')
 
-class classonlymethod(classmethod):
-    def __get__(self, instance, owner):
-        if instance is not None:
-            raise AttributeError("This method is available only on the view 
class.")
-        return super(classonlymethod, self).__get__(instance, owner)
-
 class View(object):
     """
     Intentionally simple parent class for all views. Only implements

Modified: django/trunk/docs/topics/class-based-views.txt
===================================================================
--- django/trunk/docs/topics/class-based-views.txt      2010-11-20 01:56:34 UTC 
(rev 14641)
+++ django/trunk/docs/topics/class-based-views.txt      2010-11-20 05:10:13 UTC 
(rev 14642)
@@ -537,3 +537,60 @@
 :func:`render_to_response()` implementation will override the
 versions provided by :class:`JSONResponseMixin` and
 :class:`~django.views.generic.detail.SingleObjectTemplateResponseMixin`.
+
+Decorating class-based views
+============================
+
+.. highlightlang:: python
+
+The extension of class-based views isn't limited to using mixins. You
+can use also use decorators.
+
+Decorating in URLconf
+---------------------
+
+The simplest way of decorating class-based views is to decorate the
+result of the :meth:`~django.views.generic.base.View.as_view` method.
+The easiest place to do this is in the URLconf where you deploy your
+view::
+
+    from django.contrib.auth.decorators import login_required
+    from django.views.generic import TemplateView
+
+    urlpatterns = patterns('',
+        
(r'^about/',login_required(TemplateView.as_view(template_name="secret.html"))),
+    )
+
+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 one
+of the view-like methods on the class; that is,
+:meth:`~django.views.generic.base.View.dispatch`, or one of the HTTP
+methods (:meth:`~django.views.generic.base.View.get`,
+:meth:`~django.views.generic.base.View.post` etc).
+
+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 ``method_decorator``
+decorator transforms a function decorator into a method decorator so
+that it can be used on an instance method.
+
+    from django.contrib.auth.decorators import login_required
+    from django.utils.decorators import method_decorator
+    from django.views.generic import TemplateView
+
+    class ProtectedView(TemplateView):
+        template_name = 'secret.html'
+
+        @method_decorator(login_required)
+        def dispatch(self, **kwargs):
+            return super(ProtectedView, self).dispatch(**kwargs)
+
+In this example, every instance of :class:`ProtectedView` will have
+login protection.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to django-upda...@googlegroups.com.
To unsubscribe from this group, send email to 
django-updates+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to