process_exception未被调用最常见原因是中间件注册顺序错误:须紧接securitymiddleware之后、commonmiddleware之前;异常若发生在url解析、csrf验证或更早中间件中,则根本不会进入该方法。

process_exception 为什么没被调用
最常见的情况是中间件注册位置不对。process_exception 只对“已进入视图层但视图抛出异常”的场景生效;如果异常发生在 URL 解析失败、CSRF 验证中途、或更早的中间件里(比如 SecurityMiddleware 抛出 DisallowedHost),它根本不会走到你的中间件。
必须把自定义中间件放在 MIDDLEWARE 列表靠前位置,但又不能太前——推荐紧接在 SecurityMiddleware 之后、CommonMiddleware 之前。顺序错误会导致大量真实崩溃漏捕获。
- 不要放在最后:那样连
PermissionDenied都可能被前面中间件吃掉 - 不要放在最前:比如在
SecurityMiddleware前,DisallowedHost异常直接 400 返回,不进process_exception - 验证是否生效:手动在视图里写
raise ValueError("test"),看日志和响应是否命中你的逻辑
DEBUG=False 下返回空白 500 怎么办
这不是 bug,是 Django 的安全默认行为:生产环境禁止向客户端暴露 traceback。但很多人误以为“没报错”,其实是异常被静默吞掉,只记了日志——而日志配置没跟上,就真成黑盒了。
关键动作不是“让它显示错误”,而是确保 logger.error(..., exc_info=exception) 被正确调用。缺了 exc_info=exception,日志里只有字符串,没有可追溯的 stack frame。
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
- 检查日志配置是否启用
handlers并指向文件或 Sentry - 避免在
process_exception里调用render()渲染500.html—— 模板上下文处理器可能未初始化,导致二次异常 - API 请求统一走
JsonResponse,页面请求尽量用静态 HTML 或只依赖STATIC_URL这类内置变量
DRF 项目该用 middleware 还是 exception_handler
两者不是二选一,而是分工明确:exception_handler 只处理 DRF 视图中抛出的语义化异常(如 ValidationError、NotFound),而 process_exception 是兜底的——它能捕获 ValueError、数据库连接中断、甚至中间件自己出的错。
Django 5 + DRF 3.14+ 默认行为更严格:500 类崩溃压根不进 exception_handler,必须靠中间件先拦住。
- 如果你只改了
EXCEPTION_HANDLER,但线上还出现 HTML 500 页面,说明有非 DRF 异常逃逸了 - DRF 项目建议双管齐下:用
exception_handler做精细语义处理,用中间件做最后防线 - 注意
process_exception不要 raise 新异常,否则可能卡死异步视图或流式响应
如何区分 API 和普通页面请求并返回不同响应
别信 Accept: application/json 头——测试工具、curl、甚至某些前端 SDK 会乱设,不可靠。最稳的方式是路径前缀判断。
request.path.startswith('/api/') 简单、可控、无歧义。配合白名单(如排除 /admin/、/static/)更安全。
- 不要在中间件里动态 import(比如临时导入
JsonResponse),应提前导入避免运行时异常 - 状态码要从异常对象里提取:
getattr(exception, 'status_code', 500),而不是硬编码 - 生产环境永远隐藏 traceback,但日志里必须保留完整
exc_info,这是定位问题的唯一依据
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










