在django中,中間件其實就是一個類,在一個請求到來和這個請求結束以前,django會根據本身的規則在合適的時機執行中間件中相應的方法。django
在django項目的settings模塊中,有一個 MIDDLEWARE_CLASSES 變量,其中每個元素就是一箇中間件,以下: 瀏覽器
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ]
1 from django.utils.deprecation import MiddlewareMixin 2 3 4 class Middleware1(MiddlewareMixin): 5 def process_request(self, request): print('from process_request') 6 7 def process_view(self, request, callback, callback_args, callback_kwargs): print('from process_view') 8 9 def process_template_response(self, request, response): print('from process_template_response') 10 11 def process_exception(self, request, exception): print('from process_exception') 12 13 def process_response(self, request, response): 14 print('from process_response') 15 return response
1 MIDDLEWARE = [ 2 'django.middleware.security.SecurityMiddleware', 3 'django.contrib.sessions.middleware.SessionMiddleware', 4 'django.middleware.common.CommonMiddleware', 5 'django.middleware.csrf.CsrfViewMiddleware', 6 'django.contrib.auth.middleware.AuthenticationMiddleware', 7 'django.contrib.messages.middleware.MessageMiddleware', 8 'django.middleware.clickjacking.XFrameOptionsMiddleware', 9 'Middleware.TestMiddleware.Middleware1' 10 ]
中間件提供五個鉤子函數供使用,分別是:session
process_request(self,request)
咱們來看看有多箇中間件時,Django是如何執行其中的process_request方法:ide
1 MIDDLEWARE = [ 2 'django.middleware.security.SecurityMiddleware', 3 'django.contrib.sessions.middleware.SessionMiddleware', 4 'django.middleware.common.CommonMiddleware', 5 'django.middleware.csrf.CsrfViewMiddleware', # 此項即是攔截CSRF請求的中間件 6 'django.contrib.auth.middleware.AuthenticationMiddleware', 7 'django.contrib.messages.middleware.MessageMiddleware', 8 'django.middleware.clickjacking.XFrameOptionsMiddleware', 9 'Middleware.TestMiddleware.Middleware1' 10 'Middleware.TestMiddleware.Middleware2' 11 ]
1 from django.utils.deprecation import MiddlewareMixin 2 3 4 class Middleware1(MiddlewareMixin): 5 def process_request(self, request): print('from Middleware1.process_request') 6 7 8 class Middleware2(MiddlewareMixin): 9 def process_request(self, request): print('from Middleware2.process_request')
1 from django.shortcuts import render,HttpResponse 2 3 4 def test(request): 5 print('from view func') 6 return HttpResponse('ok')
1 from Middleware1.process_request 2 from Middleware2.process_request 3 from view func
process_response(self, request, response)
1 from django.utils.deprecation import MiddlewareMixin 2 from django.shortcuts import HttpResponse 3 4 5 class Middleware1(MiddlewareMixin): 6 def process_request(self, request): print('from Middleware1.process_request') 7 8 def process_response(self, request, response): 9 print('from Middleware1.process_response') 10 return HttpResponse('ok') 11 12 13 class Middleware2(MiddlewareMixin): 14 def process_request(self, request): print('from Middleware2.process_request') 15 16 def process_response(self, request, response): 17 print('from Middleware2.process_response') 18 return HttpResponse('ok')
from Middleware1.process_request from Middleware2.process_request from view func from Middleware2.process_response from Middleware1.process_response
process_view(self, request, view_func, view_args, view_kwargs)
給上述的Middleware1和Middleware2加上process_view方法:函數
1 from django.utils.deprecation import MiddlewareMixin 2 from django.shortcuts import HttpResponse 3 4 5 class Middleware1(MiddlewareMixin): 6 def process_request(self, request): print('from Middleware1.process_request') 7 8 def process_response(self, request, response): 9 print('from Middleware1.process_response') 10 return HttpResponse('ok') 11 12 def process_view(self, request, callback, callback_args, callback_kwargs): print('from Middleware1.process_view') 13 14 15 class Middleware2(MiddlewareMixin): 16 def process_request(self, request): print('from Middleware2.process_request') 17 18 def process_response(self, request, response): 19 print('from Middleware2.process_response') 20 return HttpResponse('ok') 21 22 def process_view(self, request, callback, callback_args, callback_kwargs): print('from Middleware2.process_view')
1 from Middleware1.process_request 2 from Middleware2.process_request 3 from Middleware1.process_view 4 from Middleware2.process_view 5 from view func 6 from Middleware2.process_response 7 from Middleware1.process_response
process_exception(self, request, exception)
修改視圖函數,並給上述的Middleware1和Middleware2加上process_exception方法:spa
1 from django.shortcuts import render, HttpResponse 2 3 4 def test(request): 5 print('from view func') 6 i = 1 / 0 7 return HttpResponse('ok')
1 from django.utils.deprecation import MiddlewareMixin 2 from django.shortcuts import HttpResponse 3 4 5 class Middleware1(MiddlewareMixin): 6 def process_request(self, request): print('from Middleware1.process_request') 7 8 def process_response(self, request, response): 9 print('from Middleware1.process_response') 10 return HttpResponse('ok') 11 12 def process_view(self, request, callback, callback_args, callback_kwargs): print('from Middleware1.process_view') 13 14 def process_exception(self, request, exception): 15 print('from Middleware1.process_exception') 16 17 18 class Middleware2(MiddlewareMixin): 19 def process_request(self, request): print('from Middleware2.process_request') 20 21 def process_response(self, request, response): 22 print('from Middleware2.process_response') 23 return HttpResponse('ok') 24 25 def process_view(self, request, callback, callback_args, callback_kwargs): print('from Middleware2.process_view') 26 27 def process_exception(self, request, exception): 28 print('from Middleware2.process_exception')
from Middleware1.process_request from Middleware2.process_request from Middleware1.process_view from Middleware2.process_view from view func from Middleware2.process_exception from Middleware1.process_exception Internal Server Error: ... ZeroDivisionError: division by zero from Middleware2.process_response from Middleware1.process_response
process_template_response(self, request, response)
修改視圖函數,並給上述的Middleware1和Middleware2加上process_template_response方法:code
1 from django.shortcuts import render, HttpResponse 2 3 4 def test(request): 5 print('from view func') 6 def render(): 7 print('from render') 8 resp = HttpResponse('ok') 9 resp.render = render 10 return resp
1 from django.utils.deprecation import MiddlewareMixin 2 from django.shortcuts import HttpResponse 3 4 5 class Middleware1(MiddlewareMixin): 6 def process_request(self, request): print('from Middleware1.process_request') 7 8 def process_response(self, request, response): 9 print('from Middleware1.process_response') 10 return HttpResponse('ok') 11 12 def process_view(self, request, callback, callback_args, callback_kwargs): print('from Middleware1.process_view') 13 14 def process_exception(self, request, exception): 15 print('from Middleware1.process_exception') 16 17 def process_template_response(self, request, response): 18 print('from Middleware1.process_template_response') 19 return response 20 21 22 class Middleware2(MiddlewareMixin): 23 def process_request(self, request): print('from Middleware2.process_request') 24 25 def process_response(self, request, response): 26 print('from Middleware2.process_response') 27 return HttpResponse('ok') 28 29 def process_view(self, request, callback, callback_args, callback_kwargs): print('from Middleware2.process_view') 30 31 def process_exception(self, request, exception): 32 print('from Middleware2.process_exception') 33 34 def process_template_response(self, request, response): 35 print('from Middleware2.process_template_response') 36 return response
from Middleware1.process_request from Middleware2.process_request from Middleware1.process_view from Middleware2.process_view from view func from Middleware2.process_template_response from Middleware1.process_template_response from render from Middleware2.process_response from Middleware1.process_response
請求到達中間件以後,先按照註冊順序執行每一個註冊中間件的process_request方法,process_request方法返回的值是None,就依次執行,若是返回的值是HttpResponse對象,再也不執行後面的process_request方法,而是執行當前對應中間件的process_response方法。也就是說:以下圖,若是MIDDLEWARE中註冊了6箇中間件,執行過程當中,第3箇中間件返回了一個HttpResponse對象,那麼第四、五、6中間件的process_request和process_response方法都不執行,順序執行三、二、1中間件的process_response方法。csrf
process_request方法都執行完後,匹配路由,找到要執行的視圖函數,先不執行視圖函數,先執行中間件中的process_view方法。若是process_view方法返回None,繼續按順序執行,當全部process_view方法執行完後執行視圖函數。假如中間件3 的process_view方法返回了HttpResponse對象,則四、五、6的process_view以及視圖函數都不執行,直接從最後一箇中間件,也就是中間件6的process_response方法開始倒序執行。中間件
process_template_response和process_exception兩個方法的觸發是有條件的,執行順序也是倒序。總結全部的執行流程以下:對象