Django - How to use decorator in class-based view methods?
Since Django 1.9, as per the docs, it is possible to apply decorator in the next way:
from django.contrib.auth.decorators import login_requiredfrom django.utils.decorators import method_decorator@method_decorator(login_required, name='dispatch')class YourClassBasedView(TemplateView): ...
where name
is the name of the method to be decorated.
or in case of few decorators:
from django.contrib.auth.decorators import login_requiredfrom django.views.decorators.cache import never_cachefrom django.utils.decorators import method_decoratordecorators = [never_cache, login_required]@method_decorator(decorators, name='dispatch')class YourClassBasedView(TemplateView): ...
There is a very simple solution to achieve what you want, and it doesn't implies decorating dispatch
method. You must use the method_decorator
over your methods (get/post) and pass the decorator call (not the decorator itself) as a parameter.
In your case it would be:
from django.utils.decorators import method_decoratorclass ProfileView(View):template_name = 'index.html' # Return profile of any role (client/employee/admin) @method_decorator(login_required()) def get(self, request, *args, **kwargs): ... # Client sign up # No decorator is needed def post(self, request): ...
Note the parethesis in the login_required
decorator.
You can pass any function-oriented decorator, even a custom one. For instance:
def white_list_check(): def decorator(func): def wrapper(request, *args, **kwargs): ip = request.META.get('REMOTE_ADDR', '0.0.0.0') if ip in WHITE_LIST: return func(request, *args, **kwargs) else: return HttpResponseForbidden() return wrapper return decorator
And then, again:
class YourView(View): @method_decorator(white_list_check()) def get(self, request): ...
Some decorators like never_cache can be used in the urls.py in stead of the old way: in views.py
e.g. the never_cache decorator:
in the old style views.py:
from django.views.decorators.cache import never_cache@never_cachedef oldstyle_view(request): # and so on
when using class based views, in urls.py:
from django.views.decorators.cache import never_cacheurlpatterns = patterns('', (r'someurl/^$', never_cache(SomeClassBasedView.as_view())),)
Edit 1st aug 2015
Note: this can be handy for those views where you do not have a complete view defined in views.py, otherwhise the decorator can be applied to the depatch method in the view as well.