深入了解Django中间件及其方法


Posted in Python onJuly 26, 2019

前言

我们可以给视图函数加装饰器来判断是用户是否登录,把没有登录的用户请求跳转到登录页面等等。我们通过给几个特定视图函数加装饰器实现了这个需求,但是以后添加的视图函数可能也需要加上装饰器,这样是不是稍微有点繁琐。

因此,我们可以使用更适宜的方式来实现类似给所有请求都做相同操作的功能了——中间件.

什么是中间件?

官方的说法:

==中间件是一个用来处理Django的请求和响应的框架级别的钩子==。它是一个轻量、低级别的插件系统,用于在==全局范围内==改变Django的输入和输出。每个中间件组件负责做一些特定的功能。

由于其影响的是全局,所以需要谨慎使用,==使用不当会影响性能==。

说的直白一点,中间件可以帮助我们==在视图函数执行之前和执行之后做一些额外的操作==。

==它的本质是一个自定义类==,类中定义了几个方法,Django框架会在请求的特定时间去执行这些方法。

打开Django项目的Settings.py文件,看到下图的MIDDLEWARE配置项:

深入了解Django中间件及其方法

MIDDLEWARD配置项是一个列表,列表中是一个个字符串,这些字符串其实是一个个类,也就是一个个中间件。

自定义中间件

中间件可以定义五种方法,分别是:

  • process_request(self, request)
  • process_view(self, request, view_func, view_args, view_kwargs)
  • process_template_response(self, request, response)
  • process_exception(self, request, exception)
  • process_response(self, request, response)

以上方法的返回值可以是None,或者是一个HttpResponse对象,如果是None,则继续按照django定义的规则向后继续执行,如果是HttpResponse对象,则直接将改对象返回给用户。

重点理解process_request 与 process_response.
***

示例

from django.utils.deprecation import MiddlewareMixin


class MD1(MiddlewareMixin):

  def process_request(self, request):
    print("我是MD1的process_request方法")

  def process_response(self, request, response):
    print("我是MD1的process_response方法")
    return response


class MD2(MiddlewareMixin):

  def process_request(self, request):
    print("我是MD2的process_request方法")

  def process_response(self, request, response):
    print("我是MD2的process_response方法")
    return response

在settings.py配置文件中的MIDDLEWARE配置项加上自定义的中间件:==app名称.文件名.类名==

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',
  # 自定义中间件(注意顺序)
  'untitled01.my_middlewares.MD1',
  'untitled01.my_middlewares.MD2',
]

中间件的五种方法

process_request

==执行时间:==
在视图函数之前,在路由匹配之前
·
==参数:==
request:请求对象,与视图中用到的request参数是同一个对象
·
==返回值:==
None:按照正常的流程走
HttpResponse:接着倒序执行当前中间件的以及之前执行过的中间件的process_response方法,不再执行其它的所有方法
·
==执行顺序:==
按照MIDDLEWARE中的注册的顺序执行,也就是此列表的索引值

process_response

==执行时间:==
最后执行
·
==参数:==
request:请求对象,与视图中用到的request参数是同一个对象
response:响应对象,与视图中返回的response是同一个对象
·
==返回值:==
response:必须返回此对象,按照正常的流程走
·
==执行顺序:==
按照注册的顺序倒序执行
***

process_view

==执行时间:==
在process_request方法及路由匹配之后,视图之前
·
==参数:==
request:请求对象,与视图中用到的request参数是同一个对象
view_func:将要执行的视图函数(它是实际的函数对象,而不是函数的名称作为字符串)
view_args:url路径中将传递给视图的位置参数的元组
view_kwargs:url路径中将传递给视图的关键值参数的字典
·
==返回值:==
None:按照正常的流程走
HttpResponse:它之后的中间件的process_view,及视图不执行,执行所有中间件的process_response方法
·
==执行顺序:==
按照注册的顺序执行
***

process_exception

==此方法只在视图中触发异常时才被执行.==

==执行时间:==
视图之后,process_response之前
·
==参数:==
request:请求对象,与视图中用到的request参数是同一个对象
exception:视图函数异常产生的Exception对象
·
==返回值:==
None:按照正常的流程走
HttpResponse对象:不再执行后面的process_exception方法
·
==执行顺序:==
按照注册的顺序倒序执行
***

process_template_response

==此方法必须在视图函数返回的对象有一个render()方法(或者表明该对象是一个TemplateResponse对象或等价方法)时,才被执行.==

==执行时间:==
视图之后,process_exception之前
·
==参数:==
request:请求对象,与视图中用到的request参数是同一个对象
response:是TemplateResponse对象(由视图函数或者中间件产生)
·
==返回值:==
response:必须返回此对象,按照正常的流程走
·
==执行顺序:==
按照注册的顺序倒序执行

中间件的执行流程

请求到达中间件之后,先按照正序执行每个注册中间件的process_request方法,如果process_request方法返回的值是None,就依次执行;如果返回的值是HttpResponse对象,则不再执行后面的process_request方法,而是执行当前对象中间件的process_response方法,并将HttpResponse对象返回给浏览器。

也就是说,如果MIDDLEWARE注册了6个中间件,执行过程中,第3个中间件返回了一个HttpResponse对象,那么第4, 5, 6中间件的process_request和process_response方法都不执行,而是顺序执行3, 2, 1中间件的process_response方法。

深入了解Django中间件及其方法

process_request方法都执行完后,匹配路由,找到要执行的视图函数,先不执行视图函数,而是先执行中间件中的process_view方法,process_view方法返回None,则继续按顺序执行,所有的process_view方法执行完后,在执行视图函数。

如果中间件 3 的process_view方法返回了一个HttpResponse对象,则4, 5, 6的process_view以及视图函数都不执行了,而是直接从最后一个中间件,也就是中间件 6 的process_response方法开始倒序执行。

深入了解Django中间件及其方法

process_template_response 与 process_exception两个方法的触发是有条件的,执行顺序也是倒序。总结所有的执行流程如下:

深入了解Django中间件及其方法

深入了解Django中间件及其方法

Django请求流程图

深入了解Django中间件及其方法

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
简介二分查找算法与相关的Python实现示例
Aug 26 Python
Python设计模式编程中Adapter适配器模式的使用实例
Mar 02 Python
python 网络编程常用代码段
Aug 28 Python
解决python2.7 查询mysql时出现中文乱码
Oct 09 Python
学习Python selenium自动化网页抓取器
Jan 20 Python
基于Python中isfile函数和isdir函数使用详解
Nov 29 Python
python中wx模块的具体使用方法
May 15 Python
解决keras,val_categorical_accuracy:,0.0000e+00问题
Jul 02 Python
vscode+PyQt5安装详解步骤
Aug 12 Python
python中uuid模块实例浅析
Dec 29 Python
一文带你掌握Pyecharts地理数据可视化的方法
Feb 06 Python
能让Python提速超40倍的神器Cython详解
Jun 24 Python
如何在Django项目中引入静态文件
Jul 26 #Python
Python 画出来六维图
Jul 26 #Python
django做form表单的数据验证过程详解
Jul 26 #Python
python用win32gui遍历窗口并设置窗口位置的方法
Jul 26 #Python
解决python中导入win32com.client出错的问题
Jul 26 #Python
Django CBV类的用法详解
Jul 26 #Python
把django中admin后台界面的英文修改为中文显示的方法
Jul 26 #Python
You might like
详解:――如何将图片储存在数据库里
2006/12/05 PHP
由php if 想到的些问题
2008/03/22 PHP
php读取EXCEL文件 php excelreader读取excel文件
2012/12/06 PHP
一组PHP可逆加密解密算法实例代码
2014/01/21 PHP
php实现按照权重随机排序数据的方法
2015/01/09 PHP
再谈Yii Framework框架中的事件event原理与应用
2020/04/07 PHP
Nigma vs Alliance BO5 第二场2.14
2021/03/10 DOTA
关于jquery动态增减控件的一些想法和小插件
2010/08/01 Javascript
JavaScript类库D
2010/10/24 Javascript
JS 控件事件小结
2012/10/31 Javascript
如何获取JQUERY AJAX返回的JSON结果集实现代码
2012/12/10 Javascript
js下将阿拉伯数字每三位一逗号分隔(如:15000000转化为15,000,000)
2014/06/02 Javascript
javascript正则表达式中分组详解
2016/07/17 Javascript
ES6新特性之函数的扩展实例详解
2017/04/01 Javascript
jQuery选取所有复选框被选中的值并用Ajax异步提交数据的实例
2017/08/04 jQuery
jQuery模拟爆炸倒计时功能实例代码
2017/08/21 jQuery
react-native动态切换tab组件的方法
2018/07/07 Javascript
jQuery实现数字自动增加或者减少的动画效果示例
2018/12/11 jQuery
Vue中通过vue-router实现命名视图的问题
2020/04/23 Javascript
[01:24:51]2014 DOTA2华西杯精英邀请赛 5 25 LGD VS NewBee第二场
2014/05/26 DOTA
解决Python requests 报错方法集锦
2017/03/19 Python
numpy.linspace函数具体使用详解
2019/05/27 Python
使用pyhon绘图比较两个手机屏幕大小(实例代码)
2020/01/03 Python
Python如何将图像音视频等资源文件隐藏在代码中(小技巧)
2020/02/16 Python
Python 实现日志同时输出到屏幕和文件
2020/02/19 Python
一些常用的HTML5模式(pattern) 总结
2015/07/14 HTML / CSS
英国最大的邮寄种子和植物公司:Thompson & Morgan
2017/09/21 全球购物
澳大利亚最好的厨具店:Kitchen Warehouse
2018/03/13 全球购物
通用求职信范文模板分享
2013/12/27 职场文书
成品仓管员工作职责
2013/12/29 职场文书
教育技术学专业职业规划书
2014/03/03 职场文书
团员自我评价范文
2015/03/10 职场文书
2015年医生个人工作总结
2015/04/25 职场文书
执行力心得体会范文
2016/01/11 职场文书
JavaScript最完整的深浅拷贝实现方式详解
2022/02/28 Javascript
阿里云ECS云服务器快照的概念以及如何使用
2022/04/21 Servers