Django中间件异常场景执行顺序及处理逻辑问询
Django 中间件执行流程疑问解答
Awesome questions about Django middleware's execution flow—let's break each one down with concrete details based on how Django handles middleware under the hood:
1. 当process_request()中间件抛出异常时,会如何处理?对应的响应中间件是否会被调用?
当某个中间件的process_request()抛出异常时,Django会立刻停掉后续process_request()方法的执行,转而从当前抛出异常的中间件开始,逆序调用所有已经成功执行过process_request()的中间件的process_exception()方法。
这里分两种情况:
- 如果有某个
process_exception()能处理异常(也就是返回了一个合法的HttpResponse对象),Django会拿着这个响应,继续逆序调用所有已执行process_request()的中间件的process_response()方法,最后把处理后的响应返回给客户端。 - 如果没有任何
process_exception()能搞定这个异常,Django会生成默认的500错误响应,同样会走一遍已执行process_request()的中间件的process_response()逆序调用流程,再返回错误页面。
划重点:只有那些已经跑完process_request()的中间件,它们的process_response()才会被触发;还没轮到执行process_request()的中间件,全程不会参与响应处理。
2. 举例来说,若AuthenticationMiddleware的process_view()抛出异常,MessageMiddleware的process_response()是否会被调用?
答案是肯定会,这在Django默认的MIDDLEWARE配置下是成立的。
原因很简单:
process_view()是在所有中间件的process_request()都按顺序执行完之后,才会按同样顺序调用的。默认配置里,AuthenticationMiddleware排在MessageMiddleware前面,所以当AuthenticationMiddleware的process_view()抛异常时,MessageMiddleware的process_request()早已经执行完毕了。- 此时Django会触发
process_exception()的逆序调用,不管异常最终有没有被处理,都会进入process_response()的逆序调用流程——MessageMiddleware属于已经执行过process_request()的中间件,所以它的process_response()一定会被调用。
3. 当process_response()中间件返回响应时,后续流程会如何执行?
Django的process_response()是按和process_request()完全相反的顺序执行的。当某个中间件的process_response()返回一个响应对象时:
- 这个响应会被传递给下一个(也就是原顺序中更靠前的)中间件的
process_response()方法,每个中间件都可以对响应做修改(比如添加自定义Header、调整响应内容等)。 - 所有已经执行过
process_request()的中间件的process_response()都会被依次调用,直到最后一个中间件处理完成,响应才会被发送给客户端。
补充你未写完的场景:比如若AuthenticationMiddleware的process_view()抛出异常,完整流程是这样的:
- 立刻停止后续
process_view()方法的执行; - 从AuthenticationMiddleware开始,逆序调用所有已执行
process_request()的中间件的process_exception(); - 不管异常被处理得到自定义响应,还是生成默认500错误响应,都会进入
process_response()的逆序调用流程,所有已执行process_request()的中间件(包括MessageMiddleware)的process_response()都会运行。
内容的提问来源于stack exchange,提问作者Mangu Singh Rajpurohit
相关产品推荐
相关产品推荐

