Django出现'NoneType对象不可调用'错误,请求排查原因
TypeError: 'NoneType' object is not callable(_middleware_chain相关)的问题 问题还原
你的疑问:
我不清楚为何会出现该错误,这代表什么含义?我的站点部署在虚拟机中,运行于Web服务器平台内,是否是因为未直接托管导致的?
同时你提供了错误日志:
[26/Jan/2018 16:28:52] "GET /static/css/custom.css HTTP/1.1" 200 7346 Traceback (most recent call last): File "/usr/lib/python3.4/wsgiref/handlers.py", line 137, in run self.result = application(self.environ, self.start_response) File "/usr/local/lib/python3.4/dist-packages/django/contrib/staticfiles/handlers.py", line 67, in __call__ return super().__call__(environ, start_response) File "/usr/local/lib/python3.4/dist-packages/django/core/handlers/wsgi.py", line 146, in __call__ response = self.get_response(request) File "/usr/local/lib/python3.4/dist-packages/django/contrib/staticfiles/handlers.py", line 62, in get_response return super().get_response(request) File "/usr/local/lib/python3.4/dist-packages/django/core/handlers/base.py", line 81, in get_response response = self._middleware_chain(request) TypeError: 'NoneType' object is not callable [26/Jan/2018 16:28:52] "GET /static/css/bootstrap.min.css.map HTTP/1.1" 500 59 Traceback (most recent call last): File "/usr/lib/python3.4/wsgiref/handlers.py", line 137, in run self.result = application(self.environ, self.start_response) File "/usr/local/lib/python3.4/dist-packages/django/contrib/staticfiles/handlers.py", line 67, in __call__ return super().__call__(environ, start_response) File "/usr/local/lib/python3.4/dist-packages/django/core/handlers/wsgi.py", line 146, in __call__ response = self.get_response(request) File "/usr/local/lib/python3.4/dist-packages/django/contrib/staticfiles/handlers.py", line 62, in get_response return super().get_response(request) File "/usr/local/lib/python3.4/dist-packages/django/core/handlers/base.py", line 81, in get_response response = self._middleware_chain(request) TypeError: 'NoneType' object is not callable
错误到底是什么意思?
我先给你拆解清楚:这个错误的核心是Django在处理请求时,试图调用_middleware_chain这个对象,但它的值是None(空值)——空值当然没法被调用啦。_middleware_chain是Django把所有中间件串联起来形成的“处理链条”,请求会顺着这个链条依次经过各个中间件处理,最后生成响应。它变成空,说明中间件链的构建过程出了问题,压根没生成有效的可调用链条。
另外先回应你的疑问:虚拟机部署、非直接托管绝对不是这个错误的原因,别往这方向钻了,问题肯定出在你的Django项目配置或者代码里。
常见排查方向和解决方案
1. 先检查中间件配置有没有错
打开你的settings.py,找到MIDDLEWARE(Django 1.10及以上版本)或者MIDDLEWARE_CLASSES(旧版本)这个列表,重点排查:
- 有没有拼写错误的中间件路径?比如类名写错、模块路径打错字,导致Django找不到这个中间件。
- 是不是加了某个不存在的中间件?或者某个第三方中间件你根本没安装?
- 中间件的顺序对不对?Django对中间件顺序有严格要求,比如
SessionMiddleware必须在AuthenticationMiddleware前面,顺序错了也可能导致链条断裂。
快速排查方法:先把MIDDLEWARE列表替换成Django默认的配置,重启服务看看还报错不。如果不报错了,说明是你自定义或新增的中间件有问题,再逐个加回去测试,找出那个搞事情的家伙。
2. 自定义中间件写得不符合规范
如果你自己写了中间件,得检查是不是符合Django的要求:
- 对于Django 1.10+的中间件,必须实现
__init__和__call__方法,或者用基于函数的中间件格式。 - 旧版本的中间件要实现
process_request、process_response这些方法,注意process_request除非要直接返回响应,否则必须返回None让请求继续往下走;如果方法里出错返回了奇怪的东西,也可能搞坏中间件链。
比如如果你的自定义中间件的__call__方法没有返回可调用对象,或者初始化时抛出了没被捕获的异常,都会导致中间件链构建失败,变成None。
3. 版本兼容性问题
从日志看你用的是Python 3.4和比较旧的Django版本(看路径里的django/contrib/staticfiles/handlers.py,应该是1.10左右的版本),检查一下第三方依赖的中间件库是不是和当前Django版本不兼容。比如某个库只支持Django 1.11+,你装了之后就会导致初始化失败,中间件链出问题。
4. 静态文件配置的小插曲
虽然错误是在请求静态文件时触发的,但根源还是中间件链的问题,不过也可以顺便检查下STATIC_URL、STATIC_ROOT这些静态文件配置是否正确,确保静态文件处理器能正常工作,但这不是主要原因。
一步步排查建议
- 先备份你的
settings.py,然后把MIDDLEWARE替换成Django默认的配置,重启服务测试。 - 如果恢复正常,就逐个添加你原来的中间件,每次添加后重启测试,找到导致问题的那个。
- 针对有问题的中间件,要么修正代码,要么更换兼容的版本,或者干脆换掉它。
内容的提问来源于stack exchange,提问作者Cohen

