详解Django中间件执行顺序


Posted in Python onJuly 16, 2018

中间件

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', # 添加中间件
]

定义一个视图进行测试

def demo_view(request):
 print('view 视图被调用')
 return HttpResponse('OK')

执行结果

详解Django中间件执行顺序

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

2 执行流程

详解Django中间件执行顺序

3 多个中间件的执行顺序

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

详解Django中间件执行顺序

示例:

定义两个中间件

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

def my_middleware2(get_response):
 print('init2 被调用')
 def middleware(request):
  print('before request 2 被调用')
  response = get_response(request)
  print('after response 2 被调用')
  return response
 return middleware

注册添加两个中间件

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', # 添加
 'users.middleware.my_middleware2', # 添加
]

执行结果

init2 被调用
init 被调用
before request 被调用
before request 2 被调用
view 视图被调用
after response 2 被调用
after response 被调用

总结:中间件的本质其实就是个装饰器,对于装饰器我之前的随笔里也详细说过,装饰器的本质其实就是个闭包

详解Django中间件执行顺序

对于装饰器来说,在这里程序从上到下执行,开始记录装饰器1-3,然后读到了函数的时候,装饰器开始装饰,把函数的引用传入装饰器中,从装饰器3开始往上装饰,所以这时候开始执行装饰器3的初始化,并把装饰完的函数当做一个新的函数,再次把新的引用传入到装饰器2,接着装饰器2进行初始化,再次把新的函数的引用传入到装饰器1进行装饰,这时候装饰器1的初始化开始,并开始执行,从而接下来的执行顺序为1-3执行装饰的内容,最后再执行本来的函数,达到一个对原有函数增加功能和特性的要求。

装饰器:从程序开始的顺序,从上到下读取----》从下到上装饰----》从上到下执行

在中间件中,执行顺序等同,只不过中间件装饰的是视图函数或者是试图类,会有一个init()初始化,为了便于理解我在说明装饰器顺序的时候,那里说的初始化就是现在的init(),也就是中间件在执行上也是从最接近函数或者类的中间件开始初始化,在中间件注册时,如果有多个中间件,程序按照从上到下的顺序来确认中间件,接着执行视图函数的时候,开始从下到上的进行init(),这里的初始化init()类似于Flask框架里四种请求勾子中的请求开始前执行一次的意思,从下到上执行完init后,再从上到下执行请求前所要执行的代码,请求完成后再从下往上执行请求后的代码。

中间件:从程序开始的顺序,从上到下读取----》从下到上初始化init()----》从上到下执行请求前----》视图的请求----》从下到上执行请求后

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

Python 相关文章推荐
一个小示例告诉你Python语言的优雅之处
Jul 04 Python
Python功能键的读取方法
May 28 Python
Python实现删除文件但保留指定文件
Jun 21 Python
python监控文件或目录变化
Jun 07 Python
TF-IDF与余弦相似性的应用(二) 找出相似文章
Dec 21 Python
Python关于excel和shp的使用在matplotlib
Jan 03 Python
详解python 爬取12306验证码
May 10 Python
python itchat实现调用微信接口的第三方模块方法
Jun 11 Python
Python类中方法getitem和getattr详解
Aug 30 Python
Python 实现自动登录+点击+滑动验证功能
Jun 10 Python
详细分析Python垃圾回收机制
Jul 01 Python
python打包生成so文件的实现
Oct 30 Python
转换科学计数法的数值字符串为decimal类型的方法
Jul 16 #Python
python 不以科学计数法输出的方法
Jul 16 #Python
Django配置celery(非djcelery)执行异步任务和定时任务
Jul 16 #Python
Python中的Django基本命令实例详解
Jul 15 #Python
完美解决python中ndarray 默认用科学计数法显示的问题
Jul 14 #Python
python爬取哈尔滨天气信息
Jul 14 #Python
Python for循环中的陷阱详解
Jul 13 #Python
You might like
将数字格式的计算结果转为汉字格式
2006/10/09 PHP
zf框架的校验器InArray使用示例
2014/03/13 PHP
PHP中$this和$that指针使用实例
2015/01/06 PHP
php实现面包屑导航例子分享
2015/12/19 PHP
Yii2 rbac权限控制之菜单menu实例教程
2016/04/28 PHP
PHP观察者模式示例【Laravel框架中有用到】
2018/06/15 PHP
Javascript 判断函数类型完美解决方案
2009/09/02 Javascript
DEDECMS如何为文章添加HOT NEW标志图片
2015/08/14 Javascript
分享12个实用的jQuery代码片段
2016/03/09 Javascript
全面解析DOM操作和jQuery实现选项移动操作代码分享
2016/06/07 Javascript
完美解决JS文件页面加载时的阻塞问题
2016/12/18 Javascript
基于vue-ssr的静态网站生成器VuePress 初体验
2018/04/17 Javascript
Taro集成Redux快速上手的方法示例
2018/06/21 Javascript
在angularJs中进行数据遍历的2种方法
2018/10/08 Javascript
详解如何在Angular优雅编写HTTP请求
2018/12/05 Javascript
vue+elementUI实现表格关键字筛选高亮
2020/10/26 Javascript
解决Vue项目打包后打开index.html页面显示空白以及图片路径错误的问题
2019/10/25 Javascript
vue实现导航标题栏随页面滚动渐隐渐显效果
2020/03/12 Javascript
AngularJs的$http发送POST请求,php无法接收Post的数据问题及解决方案
2020/08/13 Javascript
[04:22]DOTA2大事件之护国神翼
2020/08/14 DOTA
Python def函数的定义、使用及参数传递实现代码
2014/08/10 Python
Python 备份程序代码实现
2017/03/06 Python
Python画柱状统计图操作示例【基于matplotlib库】
2018/07/04 Python
3分钟学会一个Python小技巧
2018/11/23 Python
PyQT5 emit 和 connect的用法详解
2019/12/13 Python
pytorch 求网络模型参数实例
2019/12/30 Python
CSS3 RGBA色彩模式使用实例讲解
2016/04/26 HTML / CSS
韩国11街:11STREET
2018/03/27 全球购物
美国珠宝店:Helzberg Diamonds
2018/10/24 全球购物
管理学专业个人求职信范文
2013/09/21 职场文书
行政人事主管岗位职责
2015/04/11 职场文书
2015年财务经理工作总结
2015/05/13 职场文书
nginx优化的六点方法
2021/03/31 Servers
Python实现生活常识解答机器人
2021/06/28 Python
java基础——多线程
2021/07/03 Java/Android
Vue3.0中Ref与Reactive的区别示例详析
2021/07/07 Vue.js