1 类视图使用装饰器
为类视图添加装饰器,可以使用两种方法。
为了理解方便,我们先来定义一个为函数视图准备的装饰器(在设计装饰器时基本都以函数视图作为考虑的被装饰对象),及一个要被装饰的类视图。
def my_decorator(func):
def wrapper(request, *args, **kwargs):
print('自定义装饰器被调用了')
print('请求路径%s' % request.path)
return func(request, *args, **kwargs)
return wrapper
class DemoView(View):
def get(self, request):
print('get方法')
return HttpResponse('ok')
def post(self, request):
print('post方法')
return HttpResponse('ok')
1.1 在URL配置中装饰
urlpatterns = [
url(r'^demo/$', my_decorate(DemoView.as_view()))
]
此种方式最简单,但因装饰行为被放置到了url配置中,单看视图的时候无法知道此视图还被添加了装饰器,不利于代码的完整性,不建议使用。
此种方式会为类视图中的所有请求方法都加上装饰器行为(因为是在视图入口处,分发请求方式前)。
1.2 在类视图中装饰
在类视图中使用为函数视图准备的装饰器时,不能直接添加装饰器,需要使用method_decorator将其转换为适用于类视图方法的装饰器。
method_decorator装饰器使用name参数指明被装饰的方法
# 为全部请求方法添加装饰器
@method_decorator(my_decorator, name='dispatch')
class DemoView(View):
def get(self, request):
print('get方法')
return HttpResponse('ok')
def post(self, request):
print('post方法')
return HttpResponse('ok')
# 为特定请求方法添加装饰器
@method_decorator(my_decorator, name='get')
class DemoView(View):
def get(self, request):
print('get方法')
return HttpResponse('ok')
def post(self, request):
print('post方法')
return HttpResponse('ok')
如果需要为类视图的多个方法添加装饰器,但又不是所有的方法(为所有方法添加装饰器参考上面例子),可以直接在需要添加装饰器的方法上使用method_decorator,如下所示
from django.utils.decorators import method_decorator
# 为特定请求方法添加装饰器
class DemoView(View):
@method_decorator(my_decorator) # 为get方法添加了装饰器
def get(self, request):
print('get方法')
return HttpResponse('ok')
@method_decorator(my_decorator) # 为post方法添加了装饰器
def post(self, request):
print('post方法')
return HttpResponse('ok')
def put(self, request): # 没有为put方法添加装饰器
print('put方法')
return HttpResponse('ok')
2 类视图Mixin扩展类
使用面向对象多继承的特性,可以通过定义父类(作为扩展类),在父类中定义想要向类视图补充的方法,类视图继承这些扩展父类,便可实现代码复用。
定义的扩展父类名称通常以Mixin结尾。
举例如下:
class MyDecoratorMixin(object):
@classmethod
def as_view(cls, *args, **kwargs):
view = super().as_view(*args, **kwargs)
view = my_decorator(view)
return view
class DemoView(MyDecoratorMixin, View):
def get(self, request):
print('get方法')
return HttpResponse('ok')
def post(self, request):
print('post方法')
return HttpResponse('ok')
class ListModelMixin(object):
"""
list扩展类
"""
def list(self, request, *args, **kwargs):
...
class CreateModelMixin(object):
"""
create扩展类
"""
def create(self, request, *args, **kwargs):
...
class BooksView(CreateModelMixin, ListModelMixin, View):
"""
同时继承两个扩展类,复用list和create方法
"""
def get(self, request):
self.list(request)
...
def post(self, request):
self.create(request)
...