process_exception
process_exception有两个参数,一个上HttpRequest对象,一个exception上视图函数异常产生的Exception对象
这个方法只有在视图函数中出现了异常才执行。它返回的值可以是一个None也可以是一个HttpResponse对象,如果是Response对象,Django将调用模版和中间件中的process_response方法,并返回给浏览器,否则将默认处理异常,如果返回一个None,则交给下一个中间件的process_exception方法来处理异常,它的执行顺序也是按照中间件的注册顺序从下往上执行
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse, render, redirect class Middle1(MiddlewareMixin): def process_request(self, request): print('这是中间件1中的process_request方法') def process_response(self, request, response): print('这是中间件1中的process_response方法') return response def process_view(self, request, view_func, view_args, view_kwargs): print('这是中间件1中的process_view方法') def process_exception(self,request, exception): print('这是中间件1中的process_exception方法') class Middle2(MiddlewareMixin): def process_request(self, request): print('这是中间件2中的process_request方法') def process_response(self, request, response): print('这是中间件2中的process_response方法') return response def process_view(self, request, view_func, view_args, view_kwargs): print('这是中间件2中的process_view方法') def process_exception(self,request, exception): print('这是中间件2中的process_exception方法')
视图函数如果正常的话
这是中间件2中的process_request方法 这是中间件1中的process_request方法 这是中间件2中的process_view方法 这是中间件1中的process_view方法 我是test视图。。。 这是中间件1中的process_response方法 这是中间件2中的process_response方法
往视图函数里写点异常在看看结果
def test(request): print('我是test视图。。。') int('weewe') return HttpResponse('ok')
结果:
这是中间件2中的process_request方法 这是中间件1中的process_request方法 这是中间件2中的process_view方法 这是中间件1中的process_view方法 我是test视图。。。 这是中间件1中的process_exception方法 这是中间件2中的process_exception方法 Internal Server Error: /test/ Traceback (most recent call last): File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\handlers\exception.py", line 41, in inner response = get_response(request) File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\handlers\base.py", line 187, in _get_response response = self.process_exception_by_middleware(e, request) File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\handlers\base.py", line 185, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) File "E:\django-project\orm_project\appTest01\views.py", line 55, in test int('weewe') ValueError: invalid literal for int() with base 10: 'weewe' 这是中间件1中的process_response方法 这是中间件2中的process_response方法 [26/Jul/2019 23:12:45] "GET /test/ HTTP/1.1" 500 69084
执行视图函数,遇到异常之后执行process_exception方法,按注册的顺序从下往上执行,执行完之后在执行process_response(从上往下)
那如果有return了呢,因为是从下往上执行的,我们给middle1加上return
结果:
这是中间件2中的process_request方法 这是中间件1中的process_request方法 这是中间件2中的process_view方法 这是中间件1中的process_view方法 我是test视图。。。 这是中间件1中的process_exception方法 这是中间件1中的process_response方法 这是中间件2中的process_response方法
当遇到process_exception里的return时,注册顺序之前的中间件的process_exception方法不走了。执行所有中间件的process_response方法
总结:
1.process_exception的执行条件是有异常时才会执行,在视图函数之后,在process_response之前
2.参数exception错误对象信息
3.返回值:None,正常走。HttpResponse对象,注册顺序之前的中间件的process_exception方法不走了。执行所有中间件的process_response方法,把process_exception里的返回值显示在浏览器上
4.执行顺序:按照注册顺序倒序执行
process_template_response
process_template_response(self, request, response)
它的参数,一个HttpRequest对象,response是TemplateResponse对象(由视图函数或者中间件产生)。
process_template_response是在视图函数执行完成后立即执行,但是它有一个前提条件,那就是视图函数返回的对象有一个render()方法(或者表明该对象是一个TemplateResponse对象或等价方法)。
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse, render, redirect class Middle1(MiddlewareMixin): def process_request(self, request): print('这是中间件1中的process_request方法') def process_response(self, request, response): print('这是中间件1中的process_response方法') return response def process_view(self, request, view_func, view_args, view_kwargs): print('这是中间件1中的process_view方法') def process_exception(self,request, exception): print('这是中间件1中的process_exception方法') def process_template_response(self, request, response): print("这是中间件1中的process_template_response方法") return response class Middle2(MiddlewareMixin): def process_request(self, request): print('这是中间件2中的process_request方法') def process_response(self, request, response): print('这是中间件2中的process_response方法') return response def process_view(self, request, view_func, view_args, view_kwargs): print('这是中间件2中的process_view方法') def process_exception(self,request, exception): print('这是中间件2中的process_exception方法') return HttpResponse(str(exception)) def process_template_response(self, request, response): print("这是中间件2中的process_template_response方法") return response
视图函数
def test(request): print('我是test视图。。。') def render(): print("我是render") return HttpResponse("render。。。") res = HttpResponse("OK") res.render = render return res
结果:
这是中间件2中的process_request方法 这是中间件1中的process_request方法 这是中间件2中的process_view方法 这是中间件1中的process_view方法 我是test视图。。。 这是中间件1中的process_template_response方法 这是中间件2中的process_template_response方法 我是render 这是中间件1中的process_response方法 这是中间件2中的process_response方法
视图函数执行完之后,立即执行了中间件的process_template_response方法,顺序是倒序,先执行middle1的,在执行middle2的,接着执行了视图函数返回的HttpResponse对象的render方法,返回了一个新的HttpResponse对象,接着执行中间件的process_response方法。
中间件的执行流程
我们了解了中间件的五个方法,以及什么时候执行,参数,返回值
请求在到达中间件之后,先按照正序执行每个中间件中的process_request方法,如果process_request返回的是None,就依次执行。如果返回的是HttpResponse对象,不在执行后面的 process_request方法,而是执行当前中间件对应的process_response方法,将HttpResponse对象返回给浏览器。也就是说,如果MIDDLEWARE中注册了6个中间件,执行过程中,第3个中间件返回了一个HttpResponse对象,那么第4,5,6中间件的process_request和process_response方法都不执行,顺序执行3,2,1中间件的process_response方法。
process_request方法都执行完后,匹配路由,找到要执行的视图函数,找到之后先不执行视图函数,先执行中间件中的process_view方法,process_view方法如果返回None,继续按顺序执行,所有process_view方法执行完 后执行视图函数。假如中间件中的第三个process_view方法返回了一个httpResponse对象,则4,5,6的processs_view以及视图函数都不执行,直接从最后一个中间件,也就是中间件6的process_response方法开始倒序执行
process_template_response和process_exception两个方法的触发是有条件的,执行顺序也是倒序,总结所有的执行流程如下
Django请求流程图