django 4.2 中异步中间件必须显式实现 __acall__,否则在 asgi 环境下会被线程池降级执行;get_response 可能返回 awaitable[httpresponse],需统一 await;orm 仍非原生异步,须用 sync_to_async 包裹。

异步中间件的调用路径在 Django 4.2 中被显式拆分
Django 3.2 的中间件只靠 __call__ 处理所有请求,框架不区分同步/异步上下文;Django 4.2 则强制要求:若中间件想真正异步运行,必须显式实现 __acall__。否则,遇到异步视图时,它会被自动包裹进线程池降级执行——不报错,但会阻塞事件循环。
常见错误现象:RuntimeWarning: SynchronousOnlyOperation 或响应延迟明显升高,尤其在 ASGI 环境下并发高时。
-
__init__签名没变(仍需接收get_response),但它的职责已纯粹为初始化,不再参与协议判断 - 同步中间件可继续用
__call__,但若混入 ASGI + async view 场景,必须确认它不依赖阻塞 I/O(如直接读文件、调用未包装的 ORM) - 写兼容中间件时,不要在
__call__里 await 任何东西;要异步,就单独写__acall__并确保get_response返回的是 awaitable
Django 4.2 的 get_response 返回值类型不可预测
在 Django 3.2 中,get_response(request) 总是返回 HttpResponse 实例;到了 Django 4.2,它可能返回 HttpResponse 或 Awaitable[HttpResponse],取决于上游中间件是否支持异步、当前是否在 ASGI 环境、以及视图本身是否为 async def。
直接对返回值做属性访问或迭代(比如 response.content 或 for chunk in response)会触发 TypeError: object Awaitable can't be used as iterable。
- 最稳妥的做法:在中间件中统一用
await get_response(request),并声明__acall__ - 若维持同步中间件,需加运行时判断:
if asyncio.iscoroutine(response): response = await response - 别在
sync_to_async里传带副作用的函数(如含print()),它在线程中执行,日志输出顺序和位置都不可控
ORM 在 Django 4.2 中仍不是原生异步的
很多人误以为升级到 Django 4.2 + psycopg3 就能直接在 async def 视图里跑 MyModel.objects.all()。事实是:Django 的 ORM 层没有异步封装,psycopg3 的异步能力被 Django 4.2 “识别”但未“暴露”给高层 API。
典型报错:RuntimeWarning: SynchronousOnlyOperation,或请求卡住、CPU 占用异常高。
- 必须用
sync_to_async包裹查询操作,例如:await sync_to_async(list)(MyModel.objects.filter()) -
sync_to_async(thread_sensitive=True)是默认且安全的选项;设为False可能导致数据库连接复用冲突 - 真要绕过 ORM 做异步 DB 访问,得直接用
psycopg.AsyncConnection,但会丢失迁移、信号、事务原子性等关键特性
CONN_MAX_AGE 和 CONN_HEALTH_CHECKS 配置不当会导致连接失效
psycopg3 对空闲连接更敏感,沿用 Django 3.2 的 CONN_MAX_AGE=0 在 ASGI 下极易触发 OperationalError: server closed the connection unexpectedly;而 CONN_HEALTH_CHECKS=False 则会让失效连接滞留,后续查询直接抛 InterfaceError。
这不是 Django 版本差异本身的问题,而是 Django 4.2 默认启用 psycopg3 后,旧配置与新驱动行为不匹配的典型表现。
-
CONN_MAX_AGE建议设为60(秒),避免太长引发数据库侧断连,也避免太短频繁重建连接 -
CONN_HEALTH_CHECKS = True必须开启,否则连接池不会主动探测并剔除失效连接 - 若用 Gunicorn + Uvicorn 组合部署,
CONN_MAX_AGE设为None仅限 worker 内复用,但需额外配 PgBouncer 等数据库端连接池
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











