process_request方法在每次http请求进入django处理流程、匹配url路由后立即调用,早于视图函数执行;仅当该中间件已启用且前面无中间件返回httpresponse时才触发,返回none则放行,返回httpresponse则中断流程并直接响应。

process_request 方法什么时候被调用
process_request 是 Django 中中间件(Middleware)的钩子方法之一,在每次 HTTP 请求刚进入 Django 的请求处理流程时立即执行,早于视图函数调用。它只在请求路径匹配 URL 路由、且中间件已启用的前提下触发;如果前面某个中间件返回了 HttpResponse(比如重定向或 403),后续中间件的 process_request 就不会执行。
注意:Django 2.0+ 推荐使用类式中间件(带 __call__ 方法),但老式函数式中间件仍支持;process_request 只存在于类式中间件中,且必须是继承自 MiddlewareMixin 或手动实现完整协议的类。
如何正确声明和注册自定义 Middleware 类
直接继承 MiddlewareMixin 是最稳妥的方式,它自动帮你桥接旧协议(process_request/process_response)到新 ASGI/WSGI 调用链。不继承它而只写空类,process_request 不会被识别。
- 在
myapp/middleware.py中定义类,必须接受get_response参数,并调用super().__init__(get_response) - 在
settings.py的MIDDLEWARE列表中按执行顺序添加字符串路径,例如'myapp.middleware.MyAuthMiddleware' - 确保该中间件位置合理:比如鉴权逻辑要放在
SessionMiddleware和AuthenticationMiddleware之后,否则request.user还未设置
示例最小可用结构:
from django.utils.deprecation import MiddlewareMixin
class MyAuthMiddleware(MiddlewareMixin):
def process_request(self, request):
if not request.path.startswith('/api/'):
return
if not hasattr(request, 'user') or not request.user.is_authenticated:
from django.http import HttpResponseForbidden
return HttpResponseForbidden('Not authenticated')
process_request 返回值的含义和常见错误
process_request 的返回值直接决定请求是否继续向下走:返回 None 表示放行;返回任意 HttpResponse 子类实例(如 HttpResponseRedirect、JsonResponse)则中断流程,Django 立即返回该响应,后续中间件和视图都不执行。
容易踩的坑:
- 忘记
return—— 写了判断但没返回HttpResponse,结果逻辑无效 - 误返回普通字符串或字典,Django 不会自动包装成响应,会抛出
TypeError: object of type 'str' is not callable - 在
process_request中修改request.POST或request.body:Django 已解析过一次,再次读取会失败(RawPostDataException),应改用process_view或提前拦截 - 对静态文件(
DEBUG=True时由开发服务器处理)也执行鉴权逻辑 —— 需加路径白名单判断,如if request.path_info.startswith(settings.STATIC_URL)
为什么有时 process_request 根本不执行
最常见原因是中间件注册顺序或条件不满足。Django 按 MIDDLEWARE 列表从上到下执行 process_request,一旦某中间件返回了响应,后面的就跳过。比如你把自定义中间件放在 SecurityMiddleware 之前,而它因 SECURE_SSL_REDIRECT=True 在非 HTTPS 下直接 301,你的逻辑就永远收不到请求。
调试建议:
- 在
process_request开头加print(f"→ {request.path}")或打日志,确认是否进入 - 检查
MIDDLEWARE是否拼写错误(比如少个点、大小写不对) - 确认该中间件没有被条件导入逻辑绕过(例如只在
DEBUG=False下才注册) - Django 4.0+ 使用
django.core.handlers.asgi.ASGIHandler时,部分老中间件写法可能失效,需确认兼容性
真正难的不是写这个方法,而是想清楚它该在哪一层介入、要不要影响后续中间件状态、以及如何跟 session、auth、csrf 协同工作 —— 这些细节不画调用链图很容易漏掉。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











