How to apply decorator do dispatch method in class

2020-07-23 03:59发布

问题:

Reading a 'ProDjango' book, I've found interesting moment about applying custom decorator to methods in class-based views.

Author says that we can either manually assign decorator to each method of class, i.e., get, post and so on, or we can add our decorator to dispatch() method and if we do so then decorator will be applied to each method of class(get, post etc)

Question is:

How actually I can apply decorator to dispatch() method of Class-based view?

回答1:

You can use the decorator method_decorator as shown here in the docs.

From the docs:

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

class ProtectedView(TemplateView):
    template_name = 'secret.html'

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

Or you can do it in your urls.py:

from django.conf.urls import patterns
from django.contrib.auth.decorators import login_required
from myapp.views import MyView

urlpatterns = patterns('',
    (r'^about/', login_required(MyView.as_view())),
)

Update:

As of Django 1.9, you can now use the method decorator at the class level. You will need to pass the name of the method to be decorated. So there's no need to override dispatch just to apply the decorator.

Example:

@method_decorator(login_required, name='dispatch')
class ProtectedView(TemplateView):
    template_name = 'secret.html'

Moreover, you can define a list or tuple of decorators and use this instead of invoking method_decorator() multiple times.

Example(the two classes below are the same):

decorators = [never_cache, login_required]

@method_decorator(decorators, name='dispatch')
class ProtectedView(TemplateView):
    template_name = 'secret.html'

@method_decorator(never_cache, name='dispatch')
@method_decorator(login_required, name='dispatch')
class ProtectedView(TemplateView):
    template_name = 'secret.html'