是,Django 3.2起__init__必须接收get_response参数;4.2强化异步支持,要求显式实现__acall__以避免隐形降级,且get_response返回值需适配同步/异步类型。

中间件类的 __init__ 方法签名是否必须接受 get_response
是,但行为有隐含变化。Django 3.2 要求中间件类的 __init__ 必须接收 get_response 参数,并在 __call__ 中调用它;Django 4.2 仍保留该要求,但对异步支持做了明确分离——如果你写的是纯同步中间件,签名不变;但若想支持异步请求,__init__ 不再负责区分协议,而是由框架根据请求类型自动选择调用 __call__(同步)或 __acall__(异步)。没加 __acall__ 的中间件在 Django 4.2 中遇到异步视图时会降级为同步执行,不报错但可能阻塞事件循环。
CommonMiddleware 的 append_slash 行为在 Django 4.2 中更严格
Django 4.2 对 URL 重写逻辑做了细化:当 append_slash=True 且原始请求未匹配任何 URL 模式时,它不再仅检查 path + '/' 是否存在,还会验证该路径是否对应一个 *可访问的、非重定向的* 视图(例如排除了返回 301/302 的模式)。这意味着你不能再依赖“加斜杠后恰好有个 redirect 视图”来触发重定向;必须确保目标路径本身是有效终端视图。Django 3.2 在这点上较宽松,容易误触发。
自定义中间件中调用 get_response(request) 的返回值类型需显式处理
在 Django 4.2 中,get_response(request) 可能返回 HttpResponse(同步)或 Awaitable[HttpResponse](异步),而 Django 3.2 始终返回同步响应。如果你的中间件里写了类似 response = get_response(request); do_something(response) 这样的代码:
- 在 Django 3.2 下始终安全
- 在 Django 4.2 下,若请求来自异步视图且中间件未声明异步支持,
get_response仍返回同步响应;但若中间件被放入异步上下文(比如在 ASGI 环境中混用了 async view 和 sync middleware),就可能拿到 awaitable,直接调用do_something会出TypeError: object Awaitable can't be used as iterable - 正确做法是:要么统一用
await get_response(request)并声明__acall__,要么在中间件开头加判断:if asyncio.iscoroutine(response): response = await response
LocaleMiddleware 和缓存中间件的交互在 Django 4.2 中更敏感
Django 4.2 强制要求:如果启用了 LocaleMiddleware,且你又用了 UpdateCacheMiddleware / FetchFromCacheMiddleware,那么 LocaleMiddleware 必须排在缓存中间件之前(即在 MIDDLEWARE 列表中位置更靠前)。否则,缓存键不会包含 Accept-Language 头,导致不同语言用户拿到同一份缓存内容。Django 3.2 虽然也推荐这个顺序,但不校验,出问题时只表现为翻译失效,排查困难。
立即学习“Python免费学习笔记(深入)”;
最易被忽略的是异步中间件的“隐形降级”——你写了同步中间件,部署到 ASGI 服务器,又用了 async view,中间件照常运行,但整个请求链被拖回同步模式,性能优势全无,还查不出错。


















