前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Django装饰器的使用 (类视图)

Django装饰器的使用 (类视图)

作者头像
kirin
发布于 2021-02-04 08:03:28
发布于 2021-02-04 08:03:28
1.2K00
代码可运行
举报
文章被收录于专栏:Kirin博客Kirin博客
运行总次数:0
代码可运行

4 类视图使用装饰器

为类视图添加装饰器,可以使用三种方法。

为了理解方便,我们先来定义一个为函数视图准备的装饰器(在设计装饰器时基本都以函数视图作为考虑的被装饰对象),及一个要被装饰的类视图。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制

 
  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’)

4.1 在URL配置中装饰

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
urlpatterns = [
 
 
  
 
  url(r’^demo/$’, my_decorate(DemoView.as_view()))
 
 
  
 
  ]

此种方式最简单,但因装饰行为被放置到了url配置中,单看视图的时候无法知道此视图还被添加了装饰器,不利于代码的完整性,不建议使用。

此种方式会为类视图中的所有请求方法都加上装饰器行为(因为是在视图入口处,分发请求方式前)。

4.2 在类视图中装饰

在类视图中使用为函数视图准备的装饰器时,不能直接添加装饰器,需要使用method_decorator将其转换为适用于类视图方法的装饰器。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from django.utils.decorators import method_decorator
 
 
  
 
  
 
 
  
 
  # 为全部请求方法添加装饰器
 
 
  
 
  class DemoView(View):
 
 
  
 
  
 
 
  
 
   @method_decorator(my_decorator)
 
 
  
 
  def dispatch(self, *args, **kwargs):
 
 
  
 
   return super().dispatch(*args, **kwargs)
 
 
  
 
  
 
 
  
 
  def get(self, request):
 
 
  
 
  print(get方法’)
 
 
  
 
   return HttpResponse(‘ok’)
 
 
  
 
  
 
 
  
 
  def post(self, request):
 
 
  
 
  print(‘post方法’)
 
 
  
 
   return HttpResponse(‘ok’)
 
 
  
 
  
 
 
  
 
  
 
 
  
 
  # 为特定请求方法添加装饰器
 
 
  
 
  class DemoView(View):
 
 
  
 
  
 
 
  
 
   @method_decorator(my_decorator)
 
 
  
 
  def get(self, request):
 
 
  
 
  print(get方法’)
 
 
  
 
   return HttpResponse(‘ok’)
 
 
  
 
  
 
 
  
 
  def post(self, request):
 
 
  
 
  print(‘post方法’)
 
 
  
 
   return HttpResponse(‘ok’)

method_decorator装饰器还支持使用name参数指明被装饰的方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  # 为全部请求方法添加装饰器
 
 
  
 
  @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???

为函数视图准备的装饰器,其被调用时,第一个参数用于接收request对象

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   def my_decorate(func):
 
 
  
 
   def wrapper(request, *args, **kwargs): # 第一个参数request对象 
 
 
  
 
  …代码省略…
 
 
  
 
   return func(request, *args, **kwargs)
 
 
  
 
   return wrapper
 

 
 

而类视图中请求方法被调用时,传入的第一个参数不是request对象,而是self 视图对象本身,第二个位置参数才是request对象

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  
 
  class DemoView(View):
 
 
  
 
   def dispatch(self, request, *args, **kwargs):
 
 
  
 
  …代码省略…
 
 
  
 
  
 
 
  
 
   def get(self, request):
 
 
  
 
  …代码省略…
 
 

所以如果直接将用于函数视图的装饰器装饰类视图方法,会导致参数传递出现问题。

method_decorator的作用是为函数视图装饰器补充第一个self参数,以适配类视图方法。

如果将装饰器本身改为可以适配类视图方法的,类似如下,则无需再使用method_decorator。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制

 
   def my_decorator(func):
 
 
  
 
   def wrapper(self, request, *args, **kwargs): # 此处增加了self 
 
 
  
 
  print(‘自定义装饰器被调用了’)
 
 
  
 
  print(‘请求路径%s’ % request.path)
 
 
  
 
   return func(self, request, *args, **kwargs) # 此处增加了self 
 
 
  
 
   return wrapper
 
 

4.3 构造Mixin扩展类

使用面向对象多继承的特性。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制

  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’)
 
 
 
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/02/03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验