Django中间件的理解

July 6, 2019

1961 8 minutes and 54 seconds
Django中间件的理解

注:middleware 和中间件在下面文章中含义相同

假设你已经阅读了 Django官方文档middleware部分 . 下面会尽可能详尽的介绍文档中提到的知识,但是还是希望你熟悉 middleware 基本的概念。

我们将讨论下面内容:

+ 什么是 middleware
+ 什么时候使用 middleware
+ 写 middleware 必须要注意的东西
  • 什么是middleware:

    middleware 是修改 django 在执行请求时过程中,可以对于 request 和 response 对象进行预处理的钩子程序。

    官方对于其的描述是:Middleware is a framework of hooks into Django’s request/response processing. It’s a light, low-level “plugin” system for globally altering Django’s input or output.

    其中需要注意的是,官方很清楚的说明了 middleware 在 django 框架内的作用和特点:light、low-level、plugin

  • 什么时候使用middleware:

    当你需要对于每一个请求都进行处理的时候,无论请求是通过HttpRequest传入进来,还是通过HttpResponse返回给客户端等等,在处理请求对象本身进行属性和特性等修改的时候都是可以通过中间件进行实现。

    Django提供了一些默认的middleware,能够对开发人员使用django框架的时候带来便利。这里根据官方文档举出一个例子作为解释:AuthenticationMiddleware

    当我们从request中取出user对象的时候,是否想象过,user对象是由谁放入request对象,并且富裕user这么多属性值得?Django想在每个view执行之前把user设置为request的属性,于是就用了一个中间件来实现这个目标。所以Django提供了可以修改request 对象的中间件AutenticationMiddleware。

  • 写middleware必须要注意的东西:

    中间件的执行顺序(非常重要)

    首先这一点官方在文档中进行了详细的图形化说明,上图示例就是来自于官方文档的中的图片。虽然图片中的内容很显然易见,但是为了统一大家的认识,这里最好还是对其进行解释一下:首先,通过图中我们可以很直接的看到横向排布的django默认的五大种中间件,这里我就不具体阐述这五种中间件的具体功能;其次,我们可以看到从上到下贯穿的五类箭头图标,而且根据HttpRequest和HttpResponse模块,很明显的划分出了两种类型,其中两种箭头是从上自下贯穿默认中间件的,三种则是相反的内容。

    这里就可以很清楚的看到,当django中间件在进行请求处理时,process_request和process_view是来自请求端的内容,并且其在middleware中的执行顺序是根据在配置文件中的middleware中自上而下的,最终其处理的属性值可以在django的view层获取的到;此外,process_response、process_exception和process_template_response是来自view层返回给请求端的内容,并且在middleware中的执行顺序跟之前介绍的HttpRequest是完全相反的。

    middleware不需要实现全部的方法

    在编写django的中间件时,我们不需要实现图示中的所有的方法,我们只需要对其中某些方法进行继承和实现就可以了,注意这里并不是说不可以实现全部的方法,而是通常情况下是没有必要实现的,而且通常情况下如果想要实现全部的方式,则需要很高深的设计,能够与view的方法相互联动在一起。例如官方的AuthenticationMiddleware只是实现了对请求的处理,没有响应的处理,此外GZipMiddleware也只是实现了对响应的处理,并没有实现对请求和view的处理。

    所以在编写django中的中间件时,一定要确认清楚当前的中间件是请求在何时进行处理和反馈才是最合理的,否则会造成不必要的性能损失。

    middleware一定是light且fast

    因为django在处理请求经过中间件时,是进行串行处理的,所以在编写中间件时必须是light和fast的,不然请求的处理过程就会很容易的被各种繁琐的数据加工处理进行延长,最后导致请求的本身处理时间变长。通过大部分的社区示例,我们可以看到的是,django的中间件通常并不包含对于文件、脚本、数据库的操作,即使是对于以上内容的操作,也是多以读取为主,万不得已的情况下,才可能出现对文件、数据库的插入和更新操作,这其中由于会产生第三方的因素造成文件、数据库的不可用状态,最后导致django请求的本身处理出现问题。

    此外,当我们在处理一些过滤性质的django中间件时,可以根据条件直接将其进行中断处理,比如当我们在process_view过程中进行过滤性质的操作时,可以通过return HttpResponse来中断后续的中间件处理,将当前的请求直接返回给前端,避免造成不必要的运算和时间浪费。