一、什么是中间件?
Django 中间件是修改 Django request 或者 response 对象的钩子,可以理解为介于 HttpRequest 与 HttpResponse 处理之间的一道处理过程。
浏览器从请求到响应的过程中,Django 需要通过很多中间件来处理。
中间件的两大作用:
| 作用 | 说明 |
|---|---|
| 修改请求 | 修改传送到 view 中的 HttpRequest 对象 |
| 修改响应 | 修改 view 返回的 HttpResponse 对象 |
典型应用场景:
-
用户认证与权限校验
-
请求日志记录
-
跨域处理
-
全站性能监控
-
请求频率限制
二、Django 默认中间件配置
中间件组件配置在 settings.py 文件的 MIDDLEWARE 选项列表中。配置中的每个字符串选项都是一个类,也就是一个中间件。
python
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', ]
默认中间件功能说明:
| 中间件 | 作用 |
|---|---|
SecurityMiddleware | 安全相关处理,如 HTTPS 重定向、安全头 |
SessionMiddleware | 启用 Session 支持 |
CommonMiddleware | 通用处理,如 URL 重定向、APPEND_SLASH |
CsrfViewMiddleware | 提供 CSRF 保护 |
AuthenticationMiddleware | 为 request 添加 user 属性 |
MessageMiddleware | 启用消息框架 |
XFrameOptionsMiddleware | 防止点击劫持攻击 |
注意:
MIDDLEWARE的顺序非常重要,它决定了中间件的执行顺序。顺序错误可能导致功能异常。
三、自定义中间件的步骤
Step 1:在 app 目录下新建 py 文件
文件名可自定义,如 middlewares.py,并导入 MiddlewareMixin:
python
from django.utils.deprecation import MiddlewareMixin
Step 2:定义中间件类
自定义的中间件类必须继承 MiddlewareMixin:
python
class MD1(MiddlewareMixin): pass
Step 3:在 settings.py 中注册
python
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.middlewares.MD1', # 注册自定义中间件 ]
注册位置决定执行顺序: 越靠前的中间件,
process_request越先执行,process_response越后执行。
四、中间件的四大方法
中间件可以定义四个方法:
| 方法 | 执行时机 |
|---|---|
process_request(self, request) | 视图函数之前 |
process_view(self, request, view_func, view_args, view_kwargs) | 视图函数之前,process_request 之后 |
process_exception(self, request, exception) | 视图函数抛出异常时 |
process_response(self, request, response) | 视图函数之后 |
五、process_request 方法
签名: process_request(self, request)
参数: request,与视图函数中的 request 是同一个对象。
返回值:
-
None:按正常流程继续走,交给下一个中间件处理。 -
HttpResponse对象:Django 将不执行后续视图函数之前的方法以及视图函数,直接以该中间件为起点,倒序执行中间件的process_response方法。
执行特点:
-
在视图函数之前执行。
-
多个中间件时,按
MIDDLEWARE注册顺序顺序执行。 -
不同中间件之间传递的 request 参数都是同一个请求对象。
示例:
python
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import render, HttpResponse class MD1(MiddlewareMixin): def process_request(self, request): print("md1 process_request 方法。", id(request)) # 在视图之前执行
返回值对流程的影响:
六、process_response 方法
签名: process_response(self, request, response)
参数:
-
request:请求对象 -
response:视图函数返回的 HttpResponse 对象
返回值: 必须要有返回值,且必须是 response。
执行特点:
-
在视图函数之后执行。
-
多个中间件时,按
MIDDLEWARE注册顺序倒序执行。
示例:
python
class MD1(MiddlewareMixin): def process_request(self, request): print("md1 process_request 方法。", id(request)) def process_response(self, request, response): print("md1 process_response 方法!", id(request)) # 在视图之后 return response
执行顺序示意:
text
请求 → MD1.process_request → MD2.process_request → 视图函数 → MD2.process_response → MD1.process_response → 响应
如果 MD1 的 process_request 有返回值:
text
请求 → MD1.process_request(返回 HttpResponse) → MD1.process_response → 响应
后面的中间件和视图函数都不会执行。
七、process_view 方法
签名: process_view(request, view_func, view_args, view_kwargs)
参数:
-
request:HttpRequest 对象 -
view_func:Django 即将使用的视图函数 -
view_args:将传递给视图的位置参数列表 -
view_kwargs:将传递给视图的关键字参数字典
注意:
view_args和view_kwargs都不包含第一个视图参数(request)。
返回值:
-
None:按正常流程继续走,交给下一个中间件处理。 -
HttpResponse对象:不执行后续视图函数之前的方法以及视图函数,直接以该中间件为起点,倒序执行process_response。 -
view_func(request):不执行后续视图函数之前的方法,提前执行视图函数,然后再倒序执行process_response。
执行特点:
-
在视图函数之前,
process_request方法之后执行。 -
当最后一个中间件的
process_request到达路由关系映射之后,返回到第一个中间件process_view,然后依次往下,到达视图函数。
示例:
python
class MD1(MiddlewareMixin): def process_request(self, request): print("md1 process_request 方法。", id(request)) def process_response(self, request, response): print("md1 process_response 方法!", id(request)) return response def process_view(self, request, view_func, view_args, view_kwargs): print("md1 process_view 方法!") # 在视图之前执行,顺序执行 # return view_func(request)
执行顺序:
text
请求 → MD1.process_request → MD2.process_request → 路由匹配 → MD1.process_view → MD2.process_view → 视图函数 → MD2.process_response → MD1.process_response → 响应
八、process_exception 方法
签名: process_exception(request, exception)
参数:
-
request:HttpRequest 对象 -
exception:视图函数异常产生的 Exception 对象
执行时机:
-
只有在视图函数中出现异常了才执行。
-
按照
settings的注册倒序执行。 -
在视图函数之后,
process_response方法之前执行。
返回值:
-
None:页面会报 500 状态码错误,视图函数不会执行。倒序执行process_exception,然后再倒序执行process_response。 -
HttpResponse对象:页面不会报错,返回状态码为 200。视图函数不执行,该中间件后续的process_exception方法也不执行,直接从最后一个中间件的process_response方法倒序开始执行。
特殊情况: 若是 process_view 方法返回视图函数,提前执行了视图函数,且视图函数报错,则无论 process_exception 方法的返回值是什么,页面都会报错,且视图函数和 process_exception 方法都不执行,直接从最后一个中间件的 process_response 方法开始倒序执行。
示例:
python
class MD1(MiddlewareMixin): def process_request(self, request): print("md1 process_request 方法。", id(request)) def process_response(self, request, response): print("md1 process_response 方法!", id(request)) return response def process_view(self, request, view_func, view_args, view_kwargs): print("md1 process_view 方法!") # return view_func(request) def process_exception(self, request, exception): print("md1 process_exception 方法!") # return HttpResponse(exception) # 返回错误信息
九、四大方法执行顺序总结
正常流程(无异常):
text
请求 ↓ MD1.process_request MD2.process_request ↓ 路由匹配 ↓ MD1.process_view MD2.process_view ↓ 视图函数 ↓ MD2.process_response MD1.process_response ↓ 响应
异常流程(视图函数抛出异常):
text
请求 ↓ MD1.process_request MD2.process_request ↓ MD1.process_view MD2.process_view ↓ 视图函数(抛出异常) ↓ MD2.process_exception MD1.process_exception ↓ MD2.process_response MD1.process_response ↓ 响应
完整流程图:
十、方法执行规律总结
| 方法 | 执行时机 | 执行顺序 | 返回值影响 |
|---|---|---|---|
process_request | 视图之前 | 顺序 | 返回 HttpResponse 则短路 |
process_view | process_request 之后,视图之前 | 顺序 | 返回 HttpResponse 则短路,返回 view_func 则提前执行视图 |
process_exception | 视图抛异常时 | 倒序 | 返回 HttpResponse 则吞掉异常 |
process_response | 视图之后 | 倒序 | 必须返回 response |
记忆口诀:
-
请求进来,顺序执行:
process_request→process_view -
响应出去,倒序执行:
process_exception→process_response -
越靠前的中间件,请求越先经过,响应越后离开
十一、实战示例:请求日志中间件
python
import time from django.utils.deprecation import MiddlewareMixin class LogMiddleware(MiddlewareMixin): def process_request(self, request): request.start_time = time.time() print(f"[请求] {request.method} {request.path}") def process_response(self, request, response): if hasattr(request, 'start_time'): duration = time.time() - request.start_time print(f"[响应] {request.path} 耗时 {duration:.3f}s 状态码 {response.status_code}") return response
注册:
python
MIDDLEWARE = [ # ... 'app01.middlewares.LogMiddleware', ]
十二、常见问题排查
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 中间件不生效 | 未在 MIDDLEWARE 中注册 | 检查注册路径是否正确 |
process_response 报错 | 忘记 return response | 必须返回 response 对象 |
| 请求被提前拦截 | 某中间件 process_request 返回了 HttpResponse | 检查各中间件的返回值 |
| 执行顺序混乱 | 注册顺序错误 | 按业务需求调整 MIDDLEWARE 顺序 |
| 异常未被捕获 | process_exception 未定义或返回 None | 定义方法并返回 HttpResponse |
| 修改 request 后视图取不到 | 中间件执行顺序问题 | request 是同一对象,注意执行先后 |
十三、小结
本篇系统讲解了 Django 中间件的核心内容:
-
作用:在请求与响应之间插入处理逻辑,可修改 request 和 response。
-
配置:在
settings.py的MIDDLEWARE中注册,顺序决定执行顺序。 -
四大方法:
-
process_request:视图之前,顺序执行。 -
process_view:路由匹配后、视图之前,顺序执行。 -
process_exception:视图抛异常时,倒序执行。 -
process_response:视图之后,倒序执行。
-
-
返回值影响:返回 HttpResponse 会短路后续流程。
掌握中间件后,你已经能够为 Django 项目添加全局性的处理逻辑。下一篇我们将学习 Django 的缓存机制,提升高并发场景下的响应速度。
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/Smell_of_earth/article/details/165831029




