前言
最近需要实现一个让Django应用template缺失的时候返回404而不是500,发现存在该问题的页面很多,于是想到通过中间件实现,代码如下:
1 | from django.template import TemplateDoesNotExist |
本以为大功告成,测试发现并没有左右,中间件未触发。因此发现自己对中间件了解不够细致,于是根据官方文档做了下笔记。也可以直接参考官方文档:https://docs.djangoproject.com/en/1.8/topics/http/middleware/
该文章的Django版本是1.8.4
正文
介绍
Django 中间件是修改 Django request 或者 response 对象的钩子,可以理解为是介于 HttpRequest 与 HttpResponse 处理之间的一道处理过程。
浏览器从请求到响应的过程中,Django 需要通过很多中间件来处理,可以看如下图所示:
在请求阶段,Django会在调用视图之前按MIDDLEWARE_CLASSES
从上至下定义的顺序应用中间件。有两个钩子可用:
在响应阶段,调用视图后,从下至上以相反的顺序应用中间件。提供三个挂钩:
process_exception()
(仅当视图引发异常时)process_template_response()
(仅适用于模板响应)process_response()
要激活中间件组件,请将其添加到MIDDLEWARE_CLASSES
Django设置的 元组中。
MIDDLEWARE_CLASSES
的顺序很重要,因为中间件可以依赖于其他中间件。
Django 默认的中间件配置:
1 | MIDDLEWARE_CLASSES = ( |
编写您自己的中间件¶
编写自己的中间件很容易。每个中间件组件都是单个Python类,该类定义以下一个或多个方法:
1 | def process_request(self, request) |
上面的是按从上往下的顺序执行的,但是process_exception和process_template_response是在特定情况下才会执行的。前2个是顺序执行,后3个是倒序执行。有多个中间件时,会按照定义的元组顺序,依次执行每个中间件的process_request,然后是每个中间件的process_view,依次类推。
SHOW CODE
1 | # setting.py |
1 | # project/app/middleware.py |
1 | # view.py |
结果:
1 | # 视图存在报错 |
注意,上面的代码是随性写的,并不确定能否跑起来,但是思想是这么回事。因为我的项目中代码逻辑更复杂一些,懒得重开一个项目写了。
总结
回到最初的问题,这里视图中模板发生了TemplateDoesNotExist
错误,按道理应该会进入process_exception
中间件,但是测试并没有进入process_exception
,但是process_template_response
是进入了。在process_template_response
打印response的状态码,发现居然是200,而process_response是500。
1 | def process_template_response(self, request, response): |
然而这里无法拿到错误对象,response.content
也是空,陷入死局了。。。
另外这里尝试在视图函数里面捕获这个错误,也无法捕获到。。。
1 | # view.py |
最终解决方法,通过 os.path.isfile()
判断模板文件是否存在:(不是什么好方法,但是可行)
1 | # view.py |
本文链接: http://www.ionluo.cn/blog/posts/e919cac4.html
版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!