Django - How to use decorator in class-based view methods? Django - How to use decorator in class-based view methods? django django

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.