1. 定义

中间件是一个钩子框架,深入到django的请求/响应处理过程中。这是一个轻量、底层插件系统,目的是全局修改django的输入或输出。每一个中间件组件都是用来处理特定的功能。例如django中间件组件:AuthenticationMiddleware用来关联请求用户,采用的方式是使用session。

2. 原理

中间件工厂是一个可调用对象,接收get_response作为参数,并返回一个中间件,返回的中间件也是一个可调用对象,接收一个request,并返回一个response,向一个view函数,中间件工厂其实很像装饰器。具体实现方式有:函数方式(像使用函数实现的装饰器)、类方式(像使用类实现的装饰器)。示例代码如下:

def simple_middleware(get_response):
# 这里添加代码:一次性配置和初始化
def middleware(request):
# 这里添加代码:在view、下一个中间件执行之前执行的代码
response = get_response(request)
# 这里添加代码:view调用之后,为每一个请求/响应代码
return response
return middleware class SimpleMiddleware(object):
def __init__(self, get_response):
self.get_response = get_response
# 这里添加代码:一次性配置和初始化 def __call__(self, request):
# 这里添加代码:在view、下一个中间件执行之前执行的代码
response = get_response(request)
# 这里添加代码:view调用之后,为每一个请求/响应代码
return response

get_response可调用对象是由django提供的:可能是一个真实的view函数(如果是最后列出的中间件)、或者中间件链中的下一个中间件。当前中间件不需要知道或者关心get_response是什么,只要明白它将呈现下一步内容。

3. 存放路径

中间件是存放在一个Python文件中,可能放在任意Python搜索文件方式的路径中,只要能够在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.middleware.clickjacking.XFrameOptionsMiddleware',
]

4. 解析步骤

根据请求阶段,在调用view函数之前,django按照定义在MIDDLEWARE中的顺序,从上往下应用中间件。请求是从上往下一层一层往下传递get_response,直到核心(view),响应则是返回来的顺序(由核心开始)。如果某一层决定短路并返回一个响应,而没有调用它的get_repsonse,那么在内部的层(包括view函数)都将被看不到请求和响应。

顺序:__call__: 前部分 --> self.get_response(request) --> 后部分

self.get_response(request)内部顺序:process_view() -> view函数

多个中间件:同名函数先执行,比如:(中间件A的__call__前部分 --> 中间件B的前部分)前部分 --> (中间件A的process_view --> 中间件B的process_view)self.get_response(request) --> (中间件B的__call__后部分 --> 中间件A的后部分)后部分

5. 中间件钩子

出了前面描述的基本请求响应中间件模式,你可以添加另外三个特殊的方法(基于类的中间件),另外还有两个函数是旧式风格(MIDDLEWARE_CLASSES):

5.1. process_view():

process_view(request, view_func, view_args, view_kwargs)

  • request:请求对象,view_func:函数对象,view_args: view的位置参数,view_kwargs: view的关键字参数,view_args和view_kwargs都不包含request对象(第一个view参数)
  • 在django调用view之前调用该函数
  • 返回None(将继续处理请求,执行其他中间件提供的process_view函数,并且核心的view函数)、或者HttpResponse对象(将不再调用下面的流程,将返回结果到前端)

5.2. process_exception():

process_exception(request, exception)

  • request:请求对象,exception: view函数抛出的一次对象
  • 当一个view抛出了异常后,将调用该函数
  • 返回None(默认异常处理流程)、或者HttpResponse对象(模板响应、中间件响应将被应用上、并且响应结果返回给浏览器)

5.3. process_template_response():

process_template_response(request, response)

  • request: 请求对象,response: 由view或者中间件返回的TemplateResponse对象
  • 在view完成执行之后调用该函数。
  • 必须返回一个实现了render方法的响应对象。通过response.template_name, response.context_data来修改传递的响应对象,也可以参加并绑定新的TemplateResponse对象。
  • 不需要明确指定render响应,影响将在所有模板响应中间件完成调用之后自动render。

5.4. process_request():

process_request(request)

  • request: 请求对象
  • 这个相当于__call__()中调用self.get_response(request)之前的代码部分
  • process_request和process_response要生效必须在__call__中明确指定调用,也可以通过继承:MiddlewareMixin类来隐式调用这两个方法。
class MiddlewareMixin(object):
def __init__(self, get_response):
self.get_response = get_response
super(MiddlewareMixin, self).__init__() def __call__(self, request):
response = None
if hasattr(self, 'process_request'):
response = self.process_request(request)
if not response:
response = self.get_response(request)
if hasattr(self, 'process_response'):
response = self.process_response(request, response)
return response

5.5. process_response():

process_response(request, response)

  • request: 请求对象,response: 响应对象
  • 这个相当于把self.get_response(request)返回的response对象,和reques对象传递给该函数,该函数在self.get_response(request)之后执行。

[TimLinux] Django 中间件的更多相关文章

  1. Django数据操作F和Q、model多对多操作、Django中间件、信号、读数据库里的数据实现分页

    models.tb.objects.all().using('default'),根据using来指定在哪个库里查询,default是settings中配置的数据库的连接名称. 外话:django中引 ...

  2. django 中间件

    django处理一个Request的过程是首先通过django 中间件,然后再通过默认的URL方式进行的.所以说我们要做的就是在django 中间件这个地方把所有Request拦截住,用我们自己的方式 ...

  3. day20 FORM补充(随时更新),F/Q操作,model之多对多,django中间件,缓存,信号

    python-day20 1.FROM生成select标签的数据应该来源于数据库. 2.model 操作 F/Q  (组合查询) 3.model 多对多操作. 4.中间件 :在请求到达url前先会经过 ...

  4. Django学习之七:Django 中间件

    目录 Django 中间件 自定义中间件 - - - 大体两种方式 将中间件移除 实例 中间件加载源码阅读 总结 Django 中间件 Tips: 更新日志: 2019.01.31 更新django中 ...

  5. Django中间件的使用

    Django中间件的使用 中间件(middleware) 中间件应用于request与服务端之间和服务端与response之间,客户端发起请求到服务端接收可以通过中间件,服务端返回响应与客户端接收响应 ...

  6. Django中间件 及 form 实现用户登陆

    Django中间件 及 form 实现用户登陆 Form 验证 密码调用md5 加密存储 form.add_error("字段名", "错误信息") 自定义错误 ...

  7. Django 2.0 学习(20):Django 中间件详解

    Django 中间件详解 Django中间件 在Django中,中间件(middleware)其实就是一个类,在请求到来和结束后,Django会根据自己的规则在合适的时机执行中间件中相应的方法. 1. ...

  8. Django中间件的5种自定义方法

    阅读目录(Content) Django中间件 自定义中间件 中间件(类)中5种方法 中间件应用场景 回到顶部(go to top) Django中间件 在http请求 到达视图函数之前   和视图函 ...

  9. Python自动化之Django中间件

    django中间件 Django请求生命周期 中间件中可以定义方法,分别是 process_request(self,request) process_view(self, request, call ...

随机推荐

  1. Abp vNext 自定义 Ef Core 仓储引发异常

    问题 在使用自定义 Ef Core 仓储和 ABP vNext 注入的默认仓储时,通过两个 Repository 进行 Join 操作,提示 Cannot use multiple DbContext ...

  2. JavaScript闭包使用姿势指南

    目录 JavaScript闭包使用姿势指南 引言 闭包的定义 来个有趣的例子吧 现在我们换个例子吧 我们再来个有趣的例子 内存泄露问题 用闭包解决递归调用问题 用闭包模拟私有方法 在循环中使用闭包 性 ...

  3. 支付宝小程序和微信小程序的区别(部分)

    支付宝小程序和微信小程序之间的互相转换 1.首先是文件名 微信小程序 wxss ------ 支付宝小程序 acss 微信小程序 wxml ------ 支付宝小程序 axml 2.调用方法前缀 微信 ...

  4. 网页版的支付宝授权登录(vue+java)

    api接口文档:https://docs.open.alipay.com/289/105656 后台管理系统原本是用账号密码登录的,不过需求要改成支付宝授权, 前端仅仅需要改登录页,以及添加一个授权返 ...

  5. Mongodb自动备份数据库并删除指定天数前的备份

    1.创建Mongodb数据库备份目录 mkdir -p /home/backup/mongod_bak/mongod_bak_now mkdir -p /home/backup/mongod_bak/ ...

  6. WordPress 添加title中的logo

    WordPress 添加title中的logo <!--网页标题左侧显示--> <link rel="icon" href="/favicon.png& ...

  7. expect 自动填充密码

    它的脚本以#!/usr/bin/expect开头,执行时用expoct,而不是bash.我的一个给samba自动创建用户并且自动填写默认密码的脚本如下: vim smb_passwd.exp #!/u ...

  8. bash:双引号和单引号

    单引号.双引号都能引用字符和字符串 单引号:'$i'仅仅是字符,没有变量的意思了 双以号:变量等能表示出来

  9. 软件测试的原则,软件测试计划:5W1H

    1.测试应该尽早介入.        2.所有的测试都应追溯到用户需求.        3.程序员应该避免检查自己的程序.除了单元测试.因为程序员对于自己的作品,思维具有局限性.无法保证测试质量.交给 ...

  10. react 组件间通信,父子间通信

    一.父组件传值给子组件 父组件向下传值是使用了props属性,在父组件定义的子组件上定义传给子组件的名字和值,然后在子组件通过this.props.xxx调用就可以了. 二.子组件传值给父组件 子组件 ...