深入理解Django的中间件middleware


Posted in Python onMarch 14, 2018

本文讲述的内容基于 Django 1.11

摘要

Django 中的中间件(middleware),是一个镶嵌到Django的request/response处理机制中的一个hooks框架,是一个修改django全局输入输出的一个底层插件系统。让我们可以自定义想要的一些功能来处理用户的请求。

在Django中,中间件其实就是一个类,在类中包含一组特定的功能,在请求到来或者结束时,Django会根据我们定义的中间件规则执行中间件中对应的方法,一个 Django 项目默认激活的中间件在我们项目中的配置中可以看到是这个样子的:

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',
]

MIDDLEWARE这里列表中的每一个元素,其实就是一个个单独的中间件,举例来说:django.middleware.csrf.CsrfViewMiddleware这个中间件,作用就是在我们的 form 表单提交请求的时候,提交的时候必须要带上csrf_token,否则就不会正确提交。

中间件使用也需要讲究顺序,下一层依赖上一层的封装,例如,我们的AuthenticationMiddleware是一个认证中间件,在session 中保存认证用户的信息,但是他必须依赖于SessionMiddleware才可以被正确使用,所以他也必须在SessionMiddleware之后。但是具体的顺序问题可以参考这里

中间件结构

中间件类中需要包含以下处理方法:

1. process_request(self, request)
2. process_view(self, request, callback, callback_args, callback_kwargs)
3. process_template_response(self, request, response)
4. process_exception(self, request, exception)
5. process_response(self, request, response)

执行过程

以我们的项目中默认中间件为例子,具体的流程如下所示:

深入理解Django的中间件middleware

中间件执行前提

中间件要按照一定的顺序一层一层的执行下去,需要按照标准返回特定的内容:

  • 如果为 None,则按照顺序继续向下执行
  • 如果为 HttpResonse 对象,则直接将这个对象返回给用户

此处有一个版本前后的区别,请大家注意区分:

在 Django1.10之后, 当某个中间件,例如CsrfViewMiddleware请求process_request没有返回 None 后,这个请求会交给CsrfViewMiddleware的process_response来返回,即返回给相同一层的中间件来返回:

深入理解Django的中间件middleware

在 Django1.10之前的版本,会返回到最底层的中间件来返回:

深入理解Django的中间件middleware

中间件方法:

1、process_request(self, request)

其中request参数就是我们的HttpRequest对象,process_request 会在每个request在被决定使用哪个view之前调用,它会返回None或HttpResponse对象

2、process_view(self, request, callback, callback_args, callback_kwargs)

其中request参数就是的HttpRequest对象,callback 就是请求被决定使用的 view 函数,书具体的函数名,不是字符串类型。callback_args和callback_kwargs是 view 函数需要接受的参数,它会返回None或HttpResponse对象

3、process_template_response(self, request, response)

其中request 是 HttpRequest 对象, response 是一个由Django view或者中间件返回的TemplateResponse 对象,process_template_response()在 view 使用 render 渲染一个模版对象完成之后被调用,它必须返回一个render 方法执行后的response对象。

4、process_exception(self, request, exception)

其中request参数就是的HttpRequest对象,exception是view函数中raise的Exception对象,当 view 函数 raise 一个 exception 的时候调用process_exception,它会返回None或HttpResponse对象

5、process_response(self, request, response)

其中request是 HttpRequest 对象,response 是一个django view或者中间件返回的 HttpResponse 或者StreamingHttpResponse对象,process_response会在所有响应到达浏览器之前被调用

中间件的详细执行流程

由于process_template_response在特定的 rander 渲染中才会被调用,所以过程中不添加该方法

深入理解Django的中间件middleware

自建中间件与执行过程测试

为了更加清晰的展示中间件的执行过程与如何自定义一个中间件,我们模拟一个简单的用户请求和中间件执行过程:

自定义中间件

from django.utils.deprecation import MiddlewareMixin
class MyMiddleware_1(MiddlewareMixin):
 def process_request(self, request):
  print("自定义 process_request 1")
  return None

 def process_response(self, request, response):
  print("自定义 process_response 1")
  return response

 def process_view(self, request, callback, callback_args, callback_kwargs):
  print("自定义 process_view 1")
  return None

 def process_exception(self, request, exception):
  print("自定义 process_exception 1")


class MyMiddleware_2(MiddlewareMixin):

 def process_request(self, request):
  print("自定义 process_request 2")
  return None

 def process_response(self, request, response):
  print("自定义 process_response 2")
  return response

 def process_view(self, request, callback, callback_args, callback_kwargs):
  print("自定义 process_view 2")
  return None

 def process_exception(self, request, exception):
  print("自定义 process_exception 2")

引入

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',
 'app01.middle_by_me.MyMiddleware_1', # 第一个自定义 middleware
 'app01.middle_by_me.MyMiddleware_2' # 第二个自定义 middleware
]

输出结果

深入理解Django的中间件middleware

自定义中间件应用场景

应用场景这个问题其实不是很好去固定,因为大家在实际使用过程中的需求都不尽相同,所以我简单的举个我可以想到的例子吧。

在不修改业务逻辑源代码的情况下,我可以使用中间件来对用户的访问进行一定的筛选过滤,或者访问控制。还有能想到的更加牛逼的操作是当源站的 CDN,请求穿透源站,middleware 判断请求的内容是否在缓存中,如果在缓存直接返回,而可以不经过业务后端逻辑,是不是很骚~

是不是很像一个所有视图函数的装饰器~~

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
python数据结构之二叉树的建立实例
Apr 29 Python
Python中处理unchecked未捕获异常实例
Jan 17 Python
Python中常见的数据类型小结
Aug 29 Python
Python处理XML格式数据的方法详解
Mar 21 Python
Python 实现随机数详解及实例代码
Apr 15 Python
Python分治法定义与应用实例详解
Jul 28 Python
Python实现使用dir获取类的方法列表
Dec 24 Python
Python devel安装失败问题解决方案
Jun 09 Python
python为什么要安装到c盘
Jul 20 Python
vscode配置anaconda3的方法步骤
Aug 08 Python
Jupyter notebook命令和编辑模式常用快捷键汇总
Nov 17 Python
Python自动化实战之接口请求的实现
May 30 Python
python批量设置多个Excel文件页眉页脚的脚本
Mar 14 #Python
浅谈python正则的常用方法 覆盖范围70%以上
Mar 14 #Python
Python使用matplotlib绘制多个图形单独显示的方法示例
Mar 14 #Python
Python使用matplotlib绘制余弦的散点图示例
Mar 14 #Python
使用Python从零开始撸一个区块链
Mar 14 #Python
Python使用matplotlib绘图无法显示中文问题的解决方法
Mar 14 #Python
Django中url的反向查询的方法
Mar 14 #Python
You might like
PHP mail 通过Windows的SMTP发送邮件失败的解决方案
2009/05/27 PHP
php类中的各种拦截器用法分析
2014/11/03 PHP
PHP register_shutdown_function()函数的使用示例
2015/06/23 PHP
PHP实现的memcache环形队列类实例
2015/07/28 PHP
PHP动态地创建属性和方法, 对象的复制, 对象的比较,加载指定的文件,自动加载类文件,命名空间
2016/05/06 PHP
Yii CDBCriteria常用方法实例小结
2017/01/19 PHP
php实现微信扫码支付
2017/03/26 PHP
jquery ajax 登录验证实现代码
2009/09/23 Javascript
在JavaScript应用中实现延迟加载的方法
2015/06/25 Javascript
Angular的事件和表单详解
2016/12/26 Javascript
如何正确理解javascript的模块化
2017/03/02 Javascript
浅谈node的事件机制
2017/10/09 Javascript
深入浅析Vue.js 中的 v-for 列表渲染指令
2018/11/19 Javascript
微信小程序canvas绘制圆角base64图片的实现
2019/08/18 Javascript
如何配置vue.config.js 处理static文件夹下的静态文件
2020/06/19 Javascript
js实现点击烟花特效
2020/10/14 Javascript
[04:16]DOTA2英雄梦之声_第09期_斧王
2014/06/21 DOTA
进一步探究Python的装饰器的运用
2015/05/05 Python
Python的Django框架中模板碎片缓存简介
2015/07/24 Python
最近Python有点火? 给你7个学习它的理由!
2017/06/26 Python
利用python如何处理百万条数据(适用java新手)
2018/06/06 Python
对Pytorch中nn.ModuleList 和 nn.Sequential详解
2019/08/18 Python
python使用yield压平嵌套字典的超简单方法
2019/11/02 Python
Pycharm无法打开双击没反应的问题及解决方案
2020/08/17 Python
Pycharm连接gitlab实现过程图解
2020/09/01 Python
详解Python中如何将数据存储为json格式的文件
2020/11/18 Python
Flask-SocketIO服务端安装及使用代码示例
2020/11/26 Python
美国大码时尚女装购物网站:ELOQUII
2017/12/28 全球购物
世界上最大的铁人三项商店:Tri UK
2020/11/04 全球购物
SQL Server提供的3种恢复模型都是什么? 有什么区别?
2012/05/13 面试题
初中生个人学习的自我评价
2013/12/04 职场文书
小学生班会演讲稿
2014/01/09 职场文书
研究生考核个人自我鉴定
2014/03/27 职场文书
写一个Python脚本下载哔哩哔哩舞蹈区的所有视频
2021/05/31 Python
html css3不拉伸图片显示效果
2021/06/07 HTML / CSS
光之国的四大叛徒:第一贝利亚导致宇宙毁灭,赛文奥特曼在榜
2022/03/18 日漫