You can't simply apply a decorator on a method in class-based views.
In order to apply decorator on a view in class-based views you need to use the method_decorator
decorator.
One option is to decorate directly a method of the class:
from django.utils.decorators import method_decorator
from django.views.decorators.cache import never_cache
from django.views.generic import TemplateView
class MyPageView(TempalteView):
template_name = 'myapp/mypage.html'
@method_decorator(never_cache)
def get(self, request, *args, **kwargs):
return super().get(request, *args, **kwargs)
This is convenient when you already defined a function directly in this class.
But if you just want to apply a decorator without an defining an override, you might want to use the class level decorator. You will need to specify the method name in the name
argument.
from django.utils.decorators import method_decorator
from django.views.decorators.cache import never_cache
from django.views.generic import TemplateView
@method_decorator(never_cache, name="get")
class MyPageView(TempalteView):
template_name = 'myapp/mypage.html'
You can have multiple decorators passed to method_decorator
as a list or a tuple.
So instead of two method_decorator
lines:
from django.utils.decorators import method_decorator
from django.views.decorators.cache import never_cache
from django.contrib.auth.decorators import permission_required
from django.views.generic import TemplateView
@method_decorator(permission_required('app.view_model', raise_exception=True), name='dispatch')
@method_decorator(never_cache, name='dispatch')
class MyPageView(TempalteView):
template_name = 'myapp/mypage.html'
You can have one method_decorator
:
from django.utils.decorators import method_decorator
from django.views.decorators.cache import never_cache
from django.contrib.auth.decorators import permission_required
from django.views.generic import TemplateView
@method_decorator([
permission_required('app.view_model', raise_exception=True),
never_cache
], name='dispatch')
class MyPageView(TempalteView):
template_name = 'myapp/mypage.html'
If you reuse the same set of decorators for many views you can extract them into a variable:
from django.utils.decorators import method_decorator
from django.views.decorators.cache import never_cache
from django.contrib.auth.decorators import permission_required
from django.views.generic import TemplateView
common_decorators = [
permission_required('app.view_model', raise_exception=True),
never_cache
]
@method_decorator(common_decorators, name='dispatch')
class MyPageView(TempalteView):
template_name = 'myapp/mypage.html'
If you want decorator to apply to all methods, then set the name to dispatch
.
from django.utils.decorators import method_decorator
from django.views.decorators.cache import never_cache
from django.views.generic import TemplateView
@method_decorator(never_cache, name="dipatch")
class MyPageView(TempalteView):
template_name = 'myapp/mypage.html'
Or you can apply the decorator in URLConf instead:
from django.views.decorators.cache import never_cache
from django.urls import path
from myapp import views
urlpatterns = [
path(
"mypage/",
never_cache(views.MyPageView.as_view()),
name="mypage",
),
]