详解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实现问号表达式(?)的方法
Nov 27 Python
Python实现多线程下载文件的代码实例
Jun 01 Python
python中 chr unichr ord函数的实例详解
Aug 06 Python
Python基于递归算法实现的汉诺塔与Fibonacci数列示例
Apr 18 Python
解决Spyder中图片显示太小的问题
Apr 27 Python
Python global全局变量函数详解
Sep 18 Python
Linux下安装python3.6和第三方库的教程详解
Nov 09 Python
对Python3+gdal 读取tiff格式数据的实例讲解
Dec 04 Python
详解js文件通过python访问数据库方法
Mar 03 Python
Django 内置权限扩展案例详解
Mar 04 Python
python安装pil库方法及代码
Jun 25 Python
Python实现蒙特卡洛算法小实验过程详解
Jul 12 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
星际流派综述
2020/03/04 星际争霸
php入门学习知识点五 关于php数组的几个基本操作
2011/07/14 PHP
PHP中几个常用的魔术常量
2012/02/23 PHP
PHP在线生成二维码(google api)的实现代码详解
2013/06/04 PHP
PHP对接微信公众平台消息接口开发流程教程
2014/03/25 PHP
PHP实现一维数组转二维数组的方法
2015/02/25 PHP
浏览器加载、渲染和解析过程黑箱简析
2012/11/29 Javascript
js调试工具Console命令详解
2014/10/21 Javascript
JavaScript中的console.trace()函数介绍
2014/12/29 Javascript
在JavaScript的AngularJS库中进行单元测试的方法
2015/06/23 Javascript
jquery UI Datepicker时间控件的使用方法(终结版)
2015/11/07 Javascript
Jquery实现仿京东商城省市联动菜单
2015/11/19 Javascript
JavaScript操作class和style样式代码详解
2016/02/13 Javascript
fullPage.js和CSS3实现全屏滚动效果
2017/05/05 Javascript
JavaScript操作文件_动力节点Java学院整理
2017/06/30 Javascript
layer弹出子iframe层父子页面传值的实现方法
2018/11/22 Javascript
改变layer confirm弹窗按钮的颜色方法
2019/09/12 Javascript
vue实现简单计算商品价格
2020/09/14 Javascript
[07:31]DOTA2卡尔工作室 英雄介绍主宰篇
2013/06/25 DOTA
[05:08]顺网杯ISS-DOTA2赛歌 少女偶像Lunar青春演绎
2013/12/05 DOTA
python生成随机验证码(中文验证码)示例
2014/04/03 Python
Python subprocess模块功能与常见用法实例详解
2018/06/28 Python
Python实现string字符串连接的方法总结【8种方式】
2018/07/06 Python
利用Python将数值型特征进行离散化操作的方法
2018/11/06 Python
python Pandas如何对数据集随机抽样
2019/07/29 Python
Python之Numpy的超实用基础详细教程
2019/10/23 Python
python tkinter GUI绘制,以及点击更新显示图片代码
2020/03/14 Python
Python类中的装饰器在当前类中的声明与调用详解
2020/04/15 Python
关于CSS Tooltips(鼠标经过时显示)的效果
2013/04/10 HTML / CSS
微信端html5页面调用分享接口示例
2018/03/14 HTML / CSS
中国高端鲜花第一品牌:roseonly(一生只送一人)
2017/02/12 全球购物
EJB包括(SessionBean,EntityBean)说出他们的生命周期,及如何管理事务的?
2013/02/17 面试题
大学生党课思想汇报
2013/12/29 职场文书
运动会解说词100字
2014/01/31 职场文书
小学班主任经验交流材料
2014/12/16 职场文书
学习委员竞选稿
2015/11/20 职场文书