Middleware

Middleware是一个镶嵌到django的request/response处理机制中的一个hooks框架。它是一个修改django全局输入输出的一个底层插件系统。

每个中间件组件负责一些特定的功能,比如说 Django包含一个 AuthenticationMiddleware的中间间,使用sessions将用户和请求联系在一起( that associates users with requests using sessions.)。

这篇文章解释了中间件如何工作,如果激活中间件,如何编写自己的中间件。django有很多内建的中间件,详细内容查看内建中间件附录。

激活中间件

要想激活中间件,需要在settings文件中的 MIDDLEWARE_CLASSES下增加。在 MIDDLEWARE_CLASSES中,每个中间件以一个字符串的形势保存。比如,下面是默认创建工程的中间件 MIDDLEWARE_CLASSES内容:

MIDDLEWARE_CLASSES = ['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

一个django工程的创建不需要任何一个中间件,即如果你喜欢的话,MIDDLEWARE_CLASSES可以为空,但是强烈建议至少包含 CommonMiddleware这个中间件。
中间件在MIDDLEWARE_CLASSES中是有顺序的,因为中间件之间有相互依赖关系。比如说AuthenticationMiddleware 在session中保存认证的用户信息,因此,它必须在 SessionMiddleware之后,详细的内容可以参考Middleware ordering

Hooks和application的顺序

在请求阶段,调用views之前,django按照MIDDLEWARE_CLASSES中定义的顺序从上到下调用中间件。有两个hooks:

  • process_request()
  • process_view()

在响应阶段,调用views之后,中间件被从下到上反向调用,有三个hooks:

  • process_exception() (只有当view中raise一个例外时)
  • process_template_response() (只有view中返回template时)
  • process_response()

如果你喜欢,可以把它比作洋葱,每个中间件就是洋葱的一层皮。
每个hooks在下面描述:

编写你自己的中间件

写一个自己的中间件很简单,每个中间件就是一个普通的python类,包含下面的一个或多个方法:

1) process_request()

process_request(request)
其中request是HttpRequest对象,process_request() 将会在每个request被决定使用哪个view之前调用,它会返回None或者一个HttpResponse对象。

  • 如果返回None,django会继续执行其他中间件的process_request(), 然后是process_view() ,然后是恰当的view函数。
  • 如果返回HttpResponse对象,它就直接返回了,不再执行其他中间件,view等。

2) process_view()

process_view(request, view_func, view_args, view_kwargs)
其中request是HttpRequest 对象, view_func是django要使用的view函数 (它是实际的函数对象,而不是函数名字的字符串) view_args是view函数的列表参数, view_kwargs是view函数的字典参数。 view_args和 view_kwargs都不需要包含request这个参数。
process_view()就在django调用view函数之前被调用。
与process_request()相同,process_request()会返回None或者一个HttpResponse对象。

  • 如果返回None,django会继续执行其他中间件的process_view(),然后是恰当的view函数。
  • 如果返回HttpResponse对象,它就直接返回了,不再执行其他中间件,view等。

Note
尽量避免使用process_request 或者process_view 来访问request.POST。但是 CsrfViewMiddleware中间件是一个例外,它提供 csrf_exempt() 和 csrf_protect() 两个装饰器来解决此问题。
Accessing request.POST inside middleware from process_request orprocess_view will prevent any view running after the middleware from being able to modify the upload handlers for the request, and should normally be avoided.
The CsrfViewMiddleware class can be considered an exception, as it provides the csrf_exempt() and csrf_protect() decorators which allow views to explicitly control at what point the CSRF validation should occur.

3) process_template_response()

process_template_response(request, response)
其中request 是 HttpRequest 对象, response 是一个由django view或者中间件返回的TemplateResponse 对象。
process_template_response()在view使用render渲染一个模版对象完成之后被调用,它必须返回一个render 方法执行后的response对象,它可以修改view中返回的 response.template_name 和 response.context_data,或者为view返回的模板增加一个商标等等。
你不需要明确的渲染响应,当所有的template响应中间件处理完成后会被自动渲染。
带有process_template_response()的中间件将会被自下而上反向执行。

4) process_response()

process_response(request, response)
其中request是 HttpRequest 对象, response 是一个django view或者中间件返回的 HttpResponse 或者StreamingHttpResponse对象。
process_response()在所有的响应被返回到浏览器之前执行。
必须返回一个 HttpResponse 或者StreamingHttpResponse 对象,它可以修改response, 或者为 HttpResponse 或StreamingHttpResponse增加一个商标等。
它不像 process_request() 和process_view() 方法可能会被跳过(在他之前有人返回了HttpResponse对象), process_response()方法一定会被执行。因此,你的process_response() 方法不能依赖于你的process_request()方法。
最后,记住在响应阶段,中间件会被反向执行,你最后在 MIDDLEWARE_CLASSES定义的中间件将会被最先执行。

处理流式响应

不同于HttpResponse,StreamingHttpResponse沒有content属性,因此中间件不能认为所有的响应都有content 属性,如果想要访问content,需要测试流式响应:

if response.streaming:
response.streaming_content = wrap_streaming_content(response.streaming_content)
else:
response.content = alter_content(response.content)

Note
streaming_content 被假定为太大而不能存放在内存中, 响应中间件可以将它包裹在一个生成器中,但是必须不能消费它,通常如下所示:

def wrap_streaming_content(content):
for chunk in content:
yield alter_content(chunk)

5) process_exception()

process_exception(request, exception)
其中request 是 HttpRequest 对象. exception是view函数中raise的Exception对象。
Django当view函数raise一个例外时调用process_exception() 。process_exception()返回None 或者HttpResponse 对象

  • 如果返回 HttpResponse 对象,template response 和response中间件会被应用, 然后在浏览器中返回结果,否则,默认的例外处理将会被使用。
    再说一遍,包含process_exception的中间件将会被反向执行,如果下面的中间件返回一个response,上面的中间间将不会被执行。

6) init()

大多数处理 process_* 方法的中间件都不需要自定义构造函数,如果你确实需要有一些全局的内容需要定义也可以使用,但是注意下面两点:

  • Django初始化中间件不会包含任何参数,所以不能在__init__ 要求任何参数;
  • 不像process_* 方法在每次请求时调用,__init__方法只会在web server首次处理请求的时候调用。

标记中间件为不可用

有时候在运行的时候决定哪个中间件是否可用是十分必要的,这种情况下你的自定义中间件__init__方法可以 raise django.core.exceptions.MiddlewareNotUsed,django将会移除中间件,并且报一个日志,如果DEBUG打开的话,可以在django.request logger里看到。(1.8之前的版本,MiddlewareNotUsed不会在日志中体现)

7)指导意见

  • 中间件不继承;
  • 中间件写在哪里都行,只需要加到MIDDLEWARE_CLASSES settings中。

来源: https://docs.djangoproject.com/en/1.9/topics/http/middleware/

django middleware介绍的更多相关文章

  1. Django Middleware简介

    1      前言 Django使用非常熟练了,各种API接口不在话下,全都搞定.为方便定位问题在每个API接口的的开始和返回的地方都加上了log打印,记录入参和返回值. 但是这样有一个问题,需要每个 ...

  2. Django框架介绍之一

    这片博文就是对django有个大概的了解,通俗的说,就是先让django跑起来. django安装 在linux上安装如下: 源码安装: tar -zxvf Django-1.9.13.tar.gz ...

  3. Django MiddleWare初识

    一.Django 中间件介绍 中间件是一个用来处理Django的请求和响应的框架级别的钩子.它是一个轻量.低级别的插件系统,用于在全局范围内改变Django的输入和输出.每个中间件组件都负责做一些特定 ...

  4. django框架介绍安装-自写框架

    原文链接:https://www.cnblogs.com/maple-shaw/p/8862330.html Web框架本质 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户 ...

  5. Django 入门介绍

    Django介绍 Django框架是PythonWeb三大主流框架之一,以其功能强大全面而受到众多开发者追捧,现如今Django已经更新到3版本,但是并不推荐使用,更多建议使用1版本. Django版 ...

  6. django中间件介绍

    在学习django中间件之前,先来认识一下django的生命周期,如下图所示: django生命周期:浏览器发送的请求会先经过wsgiref模块处理解析出request(请求数据)给到中间件,然后通过 ...

  7. Django 框架介绍

    Django 框架介绍 MVC框架和MTV框架 简单了解一下什么是MVC框架.MVC(Model View Controller),是模型(model)-视图(view)-控制器(controller ...

  8. python Django 中间件介绍

    我们一直都在使用中间件,只是没有注意到而已,打开Django项目的Settings.py文件,看到下面的MIDDLEWARE配置项,django默认自带的一些中间件: MIDDLEWARE = [ ' ...

  9. Django settings介绍

    """ Django settings for macboy project. Generated by 'django-admin startproject' usin ...

随机推荐

  1. Android 面试汇总<三>

    1.3 计算机网络 基础 Q:五层协议的体系结构分别是什么?每一层都有哪些协议? 技术点:网络模型.协议 思路:分条解释每层名字以及协议 参考回答: 物理层 数据链路层:逻辑链路控制LLC.媒体接入控 ...

  2. rocketMQ broker 分发并处理请求

    使用 netty 监听端口 // org.apache.rocketmq.remoting.netty.NettyRemotingServer#start ServerBootstrap childH ...

  3. 阶段3 2.Spring_10.Spring中事务控制_4 spring中事务控制的一组API

    分析aop的 xml 的代码.更直观一些 事务提交和回滚就是我们重复的代码 spring业余事务管理器,我们拿过来直接用就可以 提交和回滚的后面直接调用释放.所以释放资源之类就是多余的 在绑定连接到线 ...

  4. 阶段3 2.Spring_04.Spring的常用注解_4 由Component衍生的注解

    为什么要使用者三个注解 Controller:表现层 Service:业务层 Repository:持久层 在这里就是用Controller 运行也没问题 用Service Repository同样也 ...

  5. Day06:抽象类、接口和内部类(上)

    JVAV中的常量 什么是常量? 常量就是不会变化的数值 为什么需要常量? 方便使用(调用)不会变化的数值 特性 不能修改 所有对象共享 常量一定是成员 定义 public static final 类 ...

  6. CSS进阶学习

    5种主流浏览器及内核 IE  trident Chrome webkit/blink Firefox  gecko Opera presto 3%-5% Safari webkit css引入三种方式 ...

  7. mysql的最左索引匹配原则

    最近复习数据库,主要看的是mysql.很多东西忘得一干二净.看到某乎上有个答案非常给力,就记录一下,以后方便查看. 链接:https://www.zhihu.com/question/36996520 ...

  8. [转帖]Linux修改时区

    公司一台国产服务器的时间总是错的 我用 date -R 出来的结果 是 +7.0 修改办法就是 这个文档来里面的 https://www.cnblogs.com/royfans/p/8056270.h ...

  9. for (;;) 与 while (true),哪个更快?

    Java技术栈 www.javastack.cn 优秀的Java技术公众号 在 JDK8u 的 jdk 项目下做个很粗略的搜索: mymbp:/Users/me/workspace/jdk8u/jdk ...

  10. python爬取天气后报网

    前言 大二下学期的大数据技术导论课上由于需要获取数据进行分析,我决定学习python爬虫来获取数据.由于对于数据需求量相对较大,我最终选择爬取 天气后报网,该网站可以查询到全国各地多年的数据,而且相对 ...