1.class-based-views
基于类的视图的扩展并不局限于使用mixins。你也可以使用装饰器。因为基于类的视图不是函数,修饰它们的工作方式不同取决于你是使用as_view()
还是创建一个子类。
1.1Decorating in URLconf
可以通过装饰as_view()
方法的结果来调整基于类的视图。最简单的地方是在部署view的URLconf中。
from django.contrib.auth.decorators import login_required, permission_required
from django.views.generic import TemplateView
from .views import VoteView
urlpatterns = [
path('about/', login_required(TemplateView.as_view(template_name="secret.html"))),
path('vote/', permission_required('polls.can_vote')(VoteView.as_view())),
]
这种方法在每个实例的基础上应用装饰器。如果希望装饰视图的每个实例,则需要采用不同的方法了。
1.2Decorating the class
要装饰基于类的视图的每个实例,您需要装饰类定义本身。为此,您要将装饰器应用于类的dispatch()
方法。
类上的方法与独立的函数并不是完全相同的,所以你不能只对方法应用函数装饰器,你需要先把它转换成方法装饰器。method_decorator
装饰器将函数装饰器转换为方法装饰器,以便可以在实例方法上使用它。
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().dispatch(*args, **kwargs)
或者,更简单地说,您可以装饰类,并将要装饰的方法的名称作为关键字参数name传递。
@method_decorator(login_required, name='dispatch')
class ProtectedView(TemplateView):
template_name = 'secret.html'
如果在一个地方有一组通用的装饰器,你可以定义一个装饰器列表或者元组,并使用它来代替多次调用method_decorator()
。这两个类是等价的。
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'
装饰器将按照传递给装饰器的顺序处理请求。在本例中,never_cache()
将在login_requiered()
之前处理请求。
在本例中,ProtectedView
的每个实例都将具有登录保护。这些例子使用了login_required
,但是,同样的行为也可以使用LoginRequiredMixin
获得。