How to use permission_required decorators on django class-based views

There are a few strategies listed in the CBV docs:

Decorate the view when you instantiate it in your urls.py (docs)

urlpatterns = [
    path('view/',login_required(ViewSpaceIndex.as_view(..)),
    ...
]

The decorator is applied on a per-instance basis, so you can add it or remove it in different urls.py routes as needed.

Decorate your class so every instance of your view is wrapped (docs)

There’s two ways to do this:

  1. Apply method_decorator to your CBV dispatch method e.g.,

     from django.utils.decorators import method_decorator
    
     @method_decorator(login_required, name="dispatch")
     class ViewSpaceIndex(TemplateView):
         template_name="secret.html"
    

If you’re using Django < 1.9 (which you shouldn’t, it’s no longer supported) you can’t use method_decorator on the class, so you have to override the dispatch method manually:

    class ViewSpaceIndex(TemplateView):

        @method_decorator(login_required)
        def dispatch(self, *args, **kwargs):
            return super(ViewSpaceIndex, self).dispatch(*args, **kwargs)
  1. Use a mixin like django.contrib.auth.mixins.LoginRequiredMixin outlined well in the other answers here:

     from django.contrib.auth.mixins import LoginRequiredMixin
    
     class MyView(LoginRequiredMixin, View):
    
         login_url="/login/"
         redirect_field_name="redirect_to"
    

Make sure you place the mixin class first in the inheritance list (so Python’s Method Resolution Order algorithm picks the Right Thing).

The reason you’re getting a TypeError is explained in the docs:

Note:
method_decorator passes *args and **kwargs as parameters to the decorated method on the class. If your method does not accept a compatible set of parameters it will raise a TypeError exception.

Leave a Comment