类视图

1 类视图引入

以函数的方式定义的视图称为函数视图,函数视图便于理解。但是遇到一个视图对应的路径提供了多种不同HTTP请求方式的支持时,便需要在一个函数中编写不同的业务逻辑,代码可读性与复用性都不佳。

 def register(request):"""处理注册""" # 获取请求方法,判断是GET/POST请求 if request.method == 'GET': # 处理GET请求,返回注册页面 return render(request, 'register.html') else: # 处理POST请求,实现注册逻辑 return HttpResponse('这里实现注册逻辑') 

在Django中也可以使用类来定义一个视图,称为类视图。

使用类视图可以将视图对应的不同请求方式以类中的不同方法来区别定义。如下所示

from django.views.generic import Viewclass RegisterView(View): """类视图:处理注册""" def get(self, request): """处理GET请求,返回注册页面""" return render(request, 'register.html') def post(self, request): """处理POST请求,实现注册逻辑""" return HttpResponse('这里实现注册逻辑') 

类视图的好处:

  • 代码可读性好
  • 类视图相对于函数视图有更高的复用性, 如果其他地方需要用到某个类视图的某个特定逻辑,直接继承该类视图即可.

2 类视图使用

定义类视图需要继承自Django提供的父类View,可使用from django.views.generic import View或者from django.views.generic.base import View 导入,定义方式如上所示。

配置路由时,使用类视图的as_view()方法来添加。

urlpatterns = [# 视图函数:注册# url(r'^register/$', views.register, name='register'),# 类视图:注册url(r'^register/$', views.RegisterView.as_view(), name='register'), ] 

3 类视图原理

    @classonlymethoddef as_view(cls, **initkwargs): """ Main entry point for a request-response process. """ ...省略代码... def view(request, *args, **kwargs): self = cls(**initkwargs) if hasattr(self, 'get') and not hasattr(self, 'head'): self.head = self.get self.request = request self.args = args self.kwargs = kwargs # 调用dispatch方法,按照不同请求方式调用不同请求方法 return self.dispatch(request, *args, **kwargs) ...省略代码... # 返回真正的函数视图 return view def dispatch(self, request, *args, **kwargs): # Try to dispatch to the right method; if a method doesn't exist, # defer to the error handler. Also defer to the error handler if the # request method isn't on the approved list. if request.method.lower() in self.http_method_names: handler = getattr(self, request.method.lower(), self.http_method_not_allowed) else: handler = self.http_method_not_allowed return handler(request, *args, **kwargs) 

4 类视图使用装饰器

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

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

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配置中装饰

urlpatterns = [url(r'^demo/$', my_decorate(DemoView.as_view()))
]

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

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

4.2 在类视图中装饰

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

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参数指明被装饰的方法

# 为全部请求方法添加装饰器
@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对象

def my_decorate(func):def wrapper(request, *args, **kwargs): # 第一个参数request对象 ...代码省略... return func(request, *args, **kwargs) return wrapper 

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

class DemoView(View):def dispatch(self, request, *args, **kwargs): ...pass... def get(self, request): ...pass... 

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

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

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

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扩展类

使用面向对象多继承的特性. 在python3中,类的多继承的顺序会依照C3算法生成的mro来进行查找,遵循广度优先的原则.

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 MyDecoratorMixin(View):
  """
  扩展类装饰器
  """
  @classmethod
  def as_view(cls, **initkwargs):
    view = super().as_view(**initkwargs)
    view = my_decorator(view)
    return view

class MyDecoratorMixin2(View):
  """
  扩展类装饰器
  """

  @classmethod
  def as_view(cls, **initkwargs):
    view = super().as_view(**initkwargs)
    view = my_decorator2(view)
    return view

class Registers(MyDecoratorMixin, MyDecoratorMixin2):
"""
注册类视图
"""

  def get(self,request):
    return HttpResponse("get page")

  def post(self,request):
    return HttpResponse("post page")

 

使用Mixin扩展类,也会为类视图的所有请求方法都添加装饰行为。

中间件

Django中的中间件是一个轻量级、底层的插件系统,可以介入Django的请求和响应处理过程,修改Django的输入或输出。中间件的设计为开发者提供了一种无侵入式的开发方式,增强了Django框架的健壮性。

我们可以使用中间件,在Django处理视图的不同阶段对输入或输出进行干预。

1 中间件的定义方法

定义一个中间件工厂函数,然后返回一个可以别调用的中间件。

中间件工厂函数需要接收一个可以调用的get_response对象。

返回的中间件也是一个可以被调用的对象,并且像视图一样需要接收一个request对象参数,返回一个response对象。

def simple_middleware(get_response):# 此处编写的代码仅在Django第一次配置和初始化的时候执行一次。 def middleware(request): # 此处编写的代码会在每个请求处理视图前被调用。 response = get_response(request) # 此处编写的代码会在每个请求处理视图之后被调用。 return response return middleware 

例如,在users应用中新建一个middleware.py文件,

def my_middleware(get_response):print('init 被调用') def middleware(request): print('before request 被调用') response = get_response(request) print('after response 被调用') return response return middleware 

定义好中间件后,需要在settings.py 文件中添加注册中间件

MIDDLEWARE = ['django.middleware.security.SecurityMiddleware','django.contrib.sessions.middleware.SessionMiddleware','django.middleware.common.CommonMiddleware',# 'django.middleware.csrf.CsrfViewMiddleware','django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'users.middleware.my_middleware', # 添加中间件 ]

注意:Django运行在调试模式下,中间件init部分有可能被调用两次。

2 多个中间件的执行顺序,要注意顺序

  • 在请求视图被处理前,中间件由上至下依次执行
  • 在请求视图被处理后,中间件由下至上依次执行

转载于:https://www.cnblogs.com/yinjiangchong/p/9255904.html

Django的类视图和中间件相关推荐

  1. 自学Python第二十二天- Django框架(三) AJAX、文件上传、POST 请求类型之间的转换、多APP开发、iframe、验证码、分页器、类视图、中间件、信号、日志、缓存、celery异步

    Django官方文档 django 使用 AJAX django 项目中也可以使用 ajax 技术 前端 前端和其他 web 框架一样,需要注意的是,django 接收 POST 请求时,需要 csr ...

  2. 【django】类视图

    以函数的⽅式定义的视图称为函数视图,函数视图便于理解.但是遇到⼀个视图对应的路径提供了多种不同HTTP请求⽅式的⽀持时,便需要在⼀个函数中编写不同的业务逻辑,代码可读性与复⽤性都不佳. 一.类视图使⽤ ...

  3. Django框架——类视图

    目录 1.类视图的使用 2.类视图装饰器的使用 1.类视图的使用 继承View类,通过不同的请求方式定义不同的函数. 类视图的好处: (1)代码可读性好 (2)类视图相对于函数视图有更高的复用性 , ...

  4. [django] View类视图

    View--所有类视图的父类 View是所有类视图的父类,包括在之后使用的最重要的DjangoRESTframework中的所有view,都是继承于它.View可以直接从from django.vie ...

  5. Django视图之类视图与中间件

    八.类视图与中间件 8.1类视图 思考:一个视图,是否可以处理两种逻辑?比如get和post请求逻辑. 如何在一个视图中处理get和post请求 注册视图处理get和post请求 以函数的方式定义的视 ...

  6. django类视图简单使用和源码解析

    django的类视图,CBV: 我们在开始接触django的时候,习惯于使用函数编写视图,即FBV.使用FBV时,我们只需要在路由匹配时,对应的路由下找到这个函数就可以了,这样做看似很和谐,但是有的时 ...

  7. 第5天:基于类的视图与中间件

    类视图引入 类视图的定义与使用 类视图实现的原理 在类视图中使用装饰器 类视图多继承&Minx扩展类 中间件 类视图引入 以函数的方式定义的视图成为函数视图,函数视图便于理解.但是遇到一个视图 ...

  8. as 不显示gradle视图_Python构建RESTful网络服务[Django篇:基于类视图的API]

    系列文章介绍 本系列文章将详细介绍将Django官方引导教程中的投票项目改写为RESTful网络服务.Django官方教程地址https://docs.djangoproject.com/zh-han ...

  9. django class类即视图类添加装饰器的几种方法

    根据别人发布整理,个人爱好收集(原文:https://blog.csdn.net/mydistance/article/details/83958655 ) 一.定义视图类 定义类视图,且类视图继承自 ...

最新文章

  1. castle之动态代理
  2. SAP Spartacus index.html里的meta标签
  3. 构建iscsi网络存储服务
  4. nginx反向代理打印日志_nginx启用TCP反向代理日志配置
  5. PyTorch JIT与TorchScript
  6. js上拉加载ajax数据,原生ajax写的上拉加载实例
  7. c语言加速度积分得到速度_自编微积分教材-第一章 微积分漫谈(1)
  8. 零基础学python书籍-非IT行业,零基础自学Python,选什么书?
  9. 【图论】昂贵的聘礼(最短路变形)
  10. Windows 用户和内核模式
  11. 基于jqUI的日期选择(‘yy-mm-dd’)
  12. 如何测算信息化项目软件运维费?
  13. 软件测试面试题:测试报告包含哪些内容(附测试报告模板)
  14. 微信开放平台、公众号和小程序的总结
  15. SwiftUI 面试问题大全
  16. Collision Filtering(selective collisions) 碰撞过滤(选择性碰撞)
  17. 怎样根据电阻上的色环,判断电阻的大小
  18. 小白学习老九君C++笔记(10) 使用类创建对象
  19. vue element 表格增加删除修改数据
  20. 花菁染料|cas146368-08-3-齐岳生物

热门文章

  1. 获取分组后取某字段最大一条记录(求每个类别中最大的值的列表)
  2. Gibbs sampling
  3. 数据库中间件支持数据库集群方案
  4. 【WIN10】程序內文件讀取與保存
  5. win2003服务器装spl2008,打安全补丁后无法进入SQL Server Management Studio
  6. 在批处理中运行.sql文件
  7. Week4-作业1:阅读与博客
  8. NLTK学习笔记(二):文本、语料资源和WordNet汇总
  9. 输入一个正整数,求它各位数的数字之和
  10. B-Tree索引在sqlserver和mysql中的应用