14 Django組件 - Django請求生命週期、中間件

14 Django組件 - Django請求生命週期、中間件

 

1、Django請求生命週期

  在學習中間件以前,先了解一下Django的請求生命週期,以下圖:python

  1)client表明瀏覽器,瀏覽器內部爲咱們封裝了socket,Django的WSGI模塊也封裝了socket;分析:django

  2)當用戶在瀏覽器中輸入url時,瀏覽器會生成請求頭和請求體發給服務端,請求頭和請求體中會包含瀏覽器的動做(action),這個動做一般爲get或者post,體如今url之中;瀏覽器

  3)請求到達Django服務器後,首先,WSGI根據http請求協議進行解包並將請求信息封裝到HttpRequest對象中;服務器

  4)再依次通過Django的中間件的process_request方法(Django自帶7箇中間件,每一箇中間件都是一個類,類中必定有一個process_request方法);session

  5)而後經過url控制器分發後,執行對應的視圖函數,視圖函數中能夠根據請求查詢相應的數據,獲得的數據能夠再傳給模板,通過render方法渲染後返回;socket

  6)返回時再依次通過中間件的process_response方法;函數

  7)再通過WSGI模塊,WSGI將按照http協議響應格式封裝響應信息,最後返回給客戶端(瀏覽器);post

  8)客戶端瀏覽器接收到返回的數據,通過渲染後顯示給用戶;性能

2、中間件的概念

中間件,顧名思義,是介於request與response處理之間的一道處理過程,相對比較輕量級,而且在全局上改變django的輸入與輸出。由於改變的是全局,因此須要謹慎實用,用很差會影響到性能。學習

       Django的中間件的定義:

1
Middleware  is  a framework of hooks into Django’s request / response processing. <br>It’s a light, low - level 「plugin」 system  for  globally altering Django’s  input  or  output.

       若是你想修改請求,例如被傳送view中的HttpRequest對象。或者你想修改view返回的HttpResponse對象,這些均可以經過中間件(middleware)來實現。可能你還想在view執行以前作一些操做,這種狀況就能夠用 middleware來實現。

       Django默認的Middleware:

 
  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',
  ]
 

       每個中間件都有具體的功能。

3、自定義中間件

       中間件中一共有四個方法:

              process_request

    process_view

    process_exception

    process_response

一、process_request,process_response

  當用戶發起請求的時候會依次通過全部的中間件,這個時候是執行process_request,最後到達views的函數中,views函數處理後,再依次穿過中間件,這個時候是process_response,最後返回給請求者。

  上述截圖中的中間件都是django自帶的,咱們也能夠本身定義一箇中間件,即本身寫一個類,可是必須繼承MiddlewareMixin。
  需導入:from django.utils.deprecation import MiddlewareMixin

  在 views.py:  

  def index(request):
    print("view函數...")
    return HttpResponse("OK")

       在 Mymiddlewares.py:

 
  from django.utils.deprecation import MiddlewareMixin
  from django.shortcuts import HttpResponse

  class Md1(MiddlewareMixin):
    def process_request(self,request):
      print("Md1請求")
      # return HttpResponse("Md1中斷")
    def process_response(self,request,response):
      print("Md1返回")
      return response

  class Md2(MiddlewareMixin):
    def process_request(self,request):
      print("Md2請求")
                
    def process_response(self,request,response):
      print("Md2返回")
      return response
 

       打印結果:

  Md1請求
  Md2請求
  view函數...
  Md2返回
  Md1返回

       注意:若是當請求到達Md1的時候直接不符合條件返回,即return HttpResponse("Md1中斷"),程序將把請求直接發給中間件1返回,而後依次返回到請求者,結果以下:      

  Md1請求
  Md1返回

  流程圖以下:

二、process_view

  process_view(self, request, callback, callback_args, callback_kwargs)

       Mymiddlewares.py修改以下:

 
     from django.utils.deprecation import MiddlewareMixin
     from django.shortcuts import HttpResponse

        class Md1(MiddlewareMixin):
            def process_request(self,request):
                print("Md1請求")
                # return HttpResponse("Md1中斷")
            def process_response(self,request,response):
                print("Md1返回")
                return response
            def process_view(self, request, callback, callback_args, callback_kwargs):
                print("Md1view")

        class Md2(MiddlewareMixin):
            def process_request(self,request):
                print("Md2請求")
                # return HttpResponse("Md2中斷")
            def process_response(self,request,response):
                print("Md2返回")
                return response
            def process_view(self, request, callback, callback_args, callback_kwargs):
                print("Md2view")
 

       打印結果以下:

  Md1請求
  Md2請求
  Md1view
  Md2view
  view函數...
  Md2返回
  Md1返回
 

  分析上面的過程,以下面流程圖:

         

  當最後一箇中間的process_request到達路由關係映射以後,返回到中間件1的process_view,而後依次往下,到達views函數,最後經過process_response依次返回到達用戶。複製代碼

    class Md1(MiddlewareMixin):
            def process_request(self,request):
                print("Md1請求")
            def process_response(self,request,response):
                print("Md1返回")
                return response
            def process_view(self, request, callback, callback_args, callback_kwargs):
                print("callback ") # 訪問index時打印<function index at 0x0000000003EF48C8>
                # 說明callback就是當前請求url對應的視圖函數名
                response = callback(request,*callback_args,**callback_kwargs)
                return response
 

  注意:process_view若是有返回值,會越過其餘的process_view以及視圖函數,可是全部的process_response都還會執行。

三、process_exception

    process_exception(self, request, exception)

  流程圖以下:

  Mymiddlewares.py修改以下:

 
     class Md1(MiddlewareMixin):
            def process_request(self,request):
                print("Md1請求")
            def process_response(self,request,response):
                print("Md1返回")
                return response
            def process_view(self, request, callback, callback_args, callback_kwargs):
                # response=callback(request,*callback_args,**callback_kwargs)
                # return response
                print("md1 process_view...")
            def process_exception(self,request, exception):
                print("md1 process_exception...")

        class Md2(MiddlewareMixin):
            def process_request(self,request):
                print("Md2請求")
            def process_response(self,request,response):
                print("Md2返回")
                return response
            def process_view(self, request, callback, callback_args, callback_kwargs):
                print("md2 process_view...")
            def process_exception(self, request, exception):
                print("md2 process_exception...")
                return HttpResponse(exception)
 

       當視圖函數出現錯誤時,打印結果以下(頁面接收到錯誤類型):

 
    Md1請求
    Md2請求
    md1 process_view...
    md2 process_view...
    view函數...
    md2 process_exception...
    Md2返回
    Md1返回
 

4、應用案例

一、作IP訪問頻率限制

       某些IP訪問服務器的頻率太高,進行攔截,好比限制每分鐘不能超過20次。

二、URL訪問過濾

       若是用戶訪問的是login視圖(放過);

       若是訪問其餘視圖,須要檢測是否是有session認證,已經有了放行,沒有返回login,這樣就免得在多個視圖函數上寫裝飾器了!

5、源碼試讀

       做爲延伸擴展內容,建議你能夠嘗試着讀一讀下面兩個django自帶的中間件:

  'django.contrib.sessions.middleware.SessionMiddleware',
  'django.contrib.auth.middleware.AuthenticationMiddleware',
相關文章
相關標籤/搜索