详解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交换变量
Sep 06 Python
python字典多条件排序方法实例
Jun 30 Python
Python open()文件处理使用介绍
Nov 30 Python
python爬虫中get和post方法介绍以及cookie作用
Feb 08 Python
Python多层装饰器用法实例分析
Feb 09 Python
解决Pycharm无法import自己安装的第三方module问题
May 18 Python
python实现从文件中读取数据并绘制成 x y 轴图形的方法
Oct 14 Python
Python使用pandas对数据进行差分运算的方法
Dec 22 Python
Python序列化与反序列化pickle用法实例
Nov 11 Python
python列表切片和嵌套列表取值操作详解
Feb 27 Python
Selenium启动Chrome时配置选项详解
Mar 18 Python
Python实现socket库网络通信套接字
Jun 04 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
eWebEditor v3.8 商业完整版 (PHP)
2006/12/06 PHP
require(),include(),require_once()和include_once()的异同
2007/01/02 PHP
解析PHP中常见的mongodb查询操作
2013/06/20 PHP
thinkphp下MySQL数据库读写分离代码剖析
2017/04/18 PHP
详解PHP中的 input属性(隐藏 只读 限制)
2017/08/14 PHP
PHP序列化的四种实现方法与横向对比
2018/11/29 PHP
JavaScript写的一个DIV 弹出网页对话框
2009/08/14 Javascript
JavaScript中的property和attribute介绍
2011/12/26 Javascript
Javascript MVC框架Backbone.js详解
2014/09/18 Javascript
Node.js 制作实时多人游戏框架
2015/01/08 Javascript
JavaScript用select实现日期控件
2015/07/17 Javascript
jQuery.ajax 跨域请求webapi设置headers的解决方案
2016/08/08 Javascript
javascript十六进制数字和ASCII字符之间的转换方法
2016/12/27 Javascript
jquery插件ContextMenu设置右键菜单
2017/03/13 Javascript
详解如何使用webpack+es6开发angular1.x
2017/08/16 Javascript
angular 未登录状态拦截路由跳转的方法
2018/10/09 Javascript
详解在Javascript中进行面向切面编程
2019/04/28 Javascript
微信小程序封装的HTTP请求示例【附升级版】
2019/05/11 Javascript
vue中使用带隐藏文本信息的图片、图片水印的方法
2020/04/24 Javascript
JavaScript实现手机号码 3-4-4格式并控制新增和删除时光标的位置
2020/06/02 Javascript
原生js实现自定义滚动条组件
2021/01/20 Javascript
Javascript生成器(Generator)的介绍与使用
2021/01/31 Javascript
Python 返回汉字的汉语拼音
2009/02/27 Python
Python实现保证只能运行一个脚本实例
2015/06/24 Python
jupyter notebook指定启动目录的方法
2021/03/02 Python
CSS3的transition和animation的用法实例介绍
2014/08/20 HTML / CSS
几个判断型的面试题
2012/07/03 面试题
学生会主席就职演讲稿
2014/01/14 职场文书
卫校中专生的自我评价
2014/01/15 职场文书
平面设计求职信
2014/03/10 职场文书
广告宣传策划方案
2014/05/21 职场文书
2015年小学开学寄语
2015/02/27 职场文书
消防宣传语大全
2015/07/13 职场文书
2015年党风廉政建设个人总结
2015/08/18 职场文书
2016高校自主招生自荐信范文
2016/01/28 职场文书
《日月潭》教学反思
2016/02/20 职场文书