Django中间件详解:原理、方法与执行流程
本文深入解析Django中间件的运行机制与自定义方法。详细阐述process_request、process_response、process_view、process_exception及process_template_response五种核心方法的功能与触发条件,结合代码示例说明在settings.py中注册中间件的方式,并完整梳理请求从进入中间件到返回响应的正序与倒序执行流程,帮助开发者掌握全局请求处理机制。
Django中间件概述
前言
在视图函数层面,我们通常通过添加装饰器来检查用户登录状态,并将未登录用户的请求重定向至登录页面。若为每个特定视图函数单独添加此类装饰器,虽然能实现功能,但随着视图数量增加,这种重复操作显得繁琐且不易维护。
为解决上述问题,我们需要一种能够对所有请求执行统一操作的机制——中间件。
什么是中间件?
官方定义如下:
中间件是Django框架级别的处理请求和响应的钩子。它构成一个轻量级且低级别的插件系统,旨在全局范围内修改Django的输入和输出数据。每个中间件组件专注于执行特定的功能。
鉴于其影响范围覆盖全局,使用时需格外谨慎,不当配置可能导致性能下降。
通俗而言,中间件允许我们在视图函数执行前后执行额外的操作。
从本质上看,中间件是一个自定义类,其中定义了若干方法。Django框架会在请求处理的特定阶段自动调用这些方法。
查看Django项目的Settings.py文件,可以找到MIDDLEWARE配置项,如图所示:

MIDDLEWARE是一个字符串列表,列表中的每个字符串代表一个类,即一个具体的中间件实例。
自定义中间件实现
自定义中间件
中间件五种核心方法
中间件类可定义以下五种方法:
- process_request(self, request)
- process_view(self, request, view_func, view_args, view_kwargs)
- process_template_response(self, request, response)
- process_exception(self, request, exception)
- process_response(self, request, response)
上述方法的返回值可以是None,也可以是HttpResponse对象。若返回None,请求将按Django既定规则继续向后执行;若返回HttpResponse对象,则直接将该对象返回给客户端。
重点理解process_request与process_response的执行逻辑。 ***
示例
from django.utils.deprecation import MiddlewareMixin
class MD1(MiddlewareMixin):
def process_request(self, request):
print("我是MD1的process_request方法")
def process_response(self, request, response):
print("我是MD1的process_response方法")
return response
class MD2(MiddlewareMixin):
def process_request(self, request):
print("我是MD2的process_request方法")
def process_response(self, request, response):
print("我是MD2的process_response方法")
return response
在settings.py配置文件的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',
# 自定义中间件(注意顺序)
'untitled01.my_middlewares.MD1',
'untitled01.my_middlewares.MD2',
]
中间件的五种方法详解
process_request
==执行时间:==
在视图函数之前,在路由匹配之前
·
==参数:==
request:请求对象,与视图中用到的request参数是同一个对象
·
==返回值:==
None:按照正常的流程走
HttpResponse:接着倒序执行当前中间件的以及之前执行过的中间件的process_response方法,不再执行其它的所有方法
·
==执行顺序:==
按照MIDDLEWARE中的注册的顺序执行,也就是此列表的索引值
process_response
==执行时间:==
最后执行
·
==参数:==
request:请求对象,与视图中用到的request参数是同一个对象
response:响应对象,与视图中返回的response是同一个对象
·
==返回值:==
response:必须返回此对象,按照正常的流程走
·
==执行顺序:==
按照注册的顺序倒序执行
***
process_view
==执行时间:==
在process_request方法及路由匹配之后,视图之前
·
==参数:==
request:请求对象,与视图中用到的request参数是同一个对象
view_func:将要执行的视图函数(它是实际的函数对象,而不是函数的名称作为字符串)
view_args:url路径中将传递给视图的位置参数的元组
view_kwargs:url路径中将传递给视图的关键值参数的字典
·
==返回值:==
None:按照正常的流程走
HttpResponse:它之后的中间件的process_view,及视图不执行,执行所有中间件的process_response方法
·
==执行顺序:==
按照注册的顺序执行
***
process_exception
==该方法仅在视图函数抛出异常时才会被触发执行。==
==执行时间:==
视图之后,process_response之前
·
==参数:==
request:请求对象,与视图中用到的request参数是同一个对象
exception:视图函数异常产生的Exception对象
·
==返回值:==
None:按照正常的流程走
HttpResponse对象:不再执行后面的process_exception方法
·
==执行顺序:==
按照注册的顺序倒序执行
***
process_template_response
==仅当视图函数返回的对象包含render()方法(即该对象为TemplateResponse实例或具有等效方法)时,此方法才会执行。==
==执行时间:==
视图之后,process_exception之前
·
==参数:==
request:请求对象,与视图中用到的request参数是同一个对象
response:是TemplateResponse对象(由视图函数或者中间件产生)
·
==返回值:==
response:必须返回此对象,按照正常的流程走
·
==执行顺序:==
按照注册的顺序倒序执行
中间件执行流程解析
中间件的执行流程
请求到达中间件层后,首先按注册顺序正序执行各中间件的process_request方法。若某process_request返回None,则继续执行下一个;若返回HttpResponse对象,则停止后续process_request的执行,转而执行当前中间件的process_response方法,并将结果返回给浏览器。
举例说明,若MIDDLEWARE中注册了6个中间件,执行过程中第3个中间件的process_request返回了HttpResponse对象,则第4、5、6个中间件的process_request和process_response均不执行。此时,系统将按顺序执行第3、2、1个中间件的process_response方法。

所有process_request方法执行完毕后,系统进行路由匹配以定位视图函数。在调用视图函数前,先依次执行各中间件的process_view方法。若process_view返回None,则继续按顺序执行,待所有process_view执行完毕后,再调用视图函数。
若第3个中间件的process_view返回HttpResponse对象,则第4、5、6个中间件的process_view及视图函数均不再执行。系统将从最后一个中间件(即第6个)开始,倒序执行所有中间件的process_response方法。

process_template_response与process_exception两个方法的触发具有特定条件,且执行顺序为倒序。总结完整的执行流程如下:


Django请求流程图

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













