ClassBasedViewにデコレータを適用する

こんなClassBasedViewがあるとして

views.py

class LoginRequiredSampleView(TemplateView):
    template_name = 'apps/login_required.html'


なんらかのデコレータを使いたい場合、いくつか方法が考えられるのでひとつずつ試してみた。


1つめ。views.pyでlogin_requiredを呼び出して関数にする

# views.py
from django.contrib.auth.decorators import login_required
from django.views.generic import TemplateView


class LoginRequiredSampleView(TemplateView):
    template_name = 'apps/login_required.html'

login_required_view = login_required(LoginRequiredSampleView.as_view())

# urls.py
url(r'^login_required$', login_required_view)


2つめ。同じ事をurls.pyでやる

url(r'^login_required$', login_required(LoginRequiredSampleView.as_view()))


3つめ。method_decoratorを使ってdispatchに適用する

# views.py
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.views.generic import TemplateView


class LoginRequiredSampleView(TemplateView):
    template_name = 'apps/login_required.html'

    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
        return super(LoginRequiredSampleView2, self).dispatch(request, *args, **kwargs)

# urls.py
url(r'^login_required$', LoginRequiredSampleView.as_view())


FormPreviewの場合、dispatchメソッドは使われていないので、method_decoratorを使いたい場合は、__call__につければいいんじゃないかと思う。

class LoginRequiredFormPreview(FormPreview):

    @method_decorator(login_required)
    def __call__(self, request, *args, **kwargs):
        return super(LoginRequiredFormPreview, self).__call__(request, *args, **kwargs)

    def done(self, request, cleaned_data):
        # do something
        return HttpResponseRedirect('/')


WizardViewはTemplateViewのサブクラスなので、dispatchメソッドにmethod_decorator適用でいける


参考 : Django Utils | Django documentation | Django
参考 : Introduction to Class-based views | Django documentation | Django



追記


4つめ。id:hirokikyにコメントもらいまして、こんなのもあると知りました。
Class based view decorators for Django

クラスにデコレータつけるんですね