2、中間件(middleware)

1.      中間件(middleware)

Django中的中間件主要實現一些附加功能,在request被用戶handler處理前,以及用戶handler處理後生存的response進行處理。所以大部分中間件的主要功能是實現了process_request或者process_response之一,固然也能夠二者都實現,意味着該中間件涉及處處理的request和response的處理。django

1.1       類視圖

在中間件的類關係中,基本類是MiddlewareMixin,其餘全部的中間件類都繼承自該類,該類僅有一個成員變量get_response,該變量在鏈接各個中間件起着很是重要的做用。該類有兩個成員函數:__init__和__call__,前者用於實現初始化,後者執行主要的功能。session

    def __call__(self, request):函數

        response = None插件

        if hasattr(self, 'process_request'):csrf

            response = self.process_request(request)中間件

        if not response:blog

            response = self.get_response(request)繼承

        if hasattr(self, 'process_response'):遞歸

            response = self.process_response(request, response)接口

        return response

其中process_request和process_response自沒必要多言,中間件須要實現的主要功能,經過hasattr()調用,判斷當前中間件是否具備process_request和process_response,有則調用。

不一樣功能的中間件,根據要完成的功能,能夠擴展本身的成員變量和成員函數,一般,自定義的成員函數被process_request和process_response調用,即這些自定義的成員函數一般不對外開放。

       其中,__init__成員函數有入參函數之一: get_response,這在後續的加載中間件時很重要好。

下圖是中間件SecurityMiddleware類的類視圖關係圖,其餘中間件的視圖關係相似。

 

1.2       中間件初始化

在工程的配置文件(Project/Project/setting.py)中指定要使用的中間件,注意各插件在序列中的順序,這決定了當請求到來時,各個中間件的執行順序,排在最前面的中間件獲得最早執行,最後的中間件最後執行。其表現一般以下所示:

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

]

下面來看,中間件是如何被加載和初始化的。class BaseHandler(object):中定義了load_middleware接口,具體細節以下:

 

handler = convert_exception_to_response(self._get_response)  /*handler[0]*/

for middleware_path in reversed(settings.MIDDLEWARE):
    middleware = import_string(middleware_path)

    mw_instance = middleware(handler)
    handler = convert_exception_to_response(mw_instance) /*handler[i]*/

 

self._middleware_chain = handler                    /*handler[end]*/

 

在上述例程中,開始遍歷全部中間件以前,handler(即handler[0])賦值給調用實體的_get_response成員函數。                   (好比class WSGIHandler(base.BaseHandler),WSGIHandler. load_middleware()調用以後,handler[0] = WSGIHandler._get_response = BaseHandler._get_response())。遍歷全部中間件過程當中,加載並初始化(middleware()調用對應着__init__成員函數)中間件,所以中間件的get_response賦值爲handler[i],注意middleware()返回一箇中間件類實體,接着調用調用handler  = convert_exception_to_response (mw_instance),convert_exception_to_response只是對輸入函數進行了容錯封裝,在分析邏輯時,能夠簡單當作輸入函數自己,所以,能夠當作handler = mw_instance(request),對於一個類實體調用即調用__call__成員函數,從目前來看,大部分的中間件並無重載該成員函數,所以是直接調用基類的成員函數,即: MiddlewareMixin. __call__(self)。所以handler[i] = MiddlewareMixin. __call__(self)。注意該函數有一個self輸入參數,各個中間件在調用時,傳入該中間件對應的self實體,這樣self.process_request, self.process_response的調用就分別對應着不一樣中間夾的處理函數。load_middleware()調用以後,各個中間件經過get_response連接起來,這樣一個request請求到來時,能夠順序經過各個中間件依次進行處理,以下圖所示:

 

在調用的最後,將self._middleware_chain = handler[end],相似於將中間件鏈表的鏈表頭保存起來,下次處理時,從該鏈表頭開始進行遍歷處理。

1.3       中間件使用

各個中間件的調用順序以下遞歸圖所示:

 

在類視圖一節中對__call__基類成員函數進行過介紹,該函數主要有前後執行的三個函數構成:process_request()、get_response()、process_response(),而get_response()一般指向下一個中間件的__call__成員函數(中間件鏈表的最後一箇中間件除外,其get_response()指向handler[0]),因爲各個中間件的get_response()這一特性(絕大部分指向基類__call__成員函數),使得中間件鏈表處理有點相似遞歸調用的感受。A,B,A1,B1,A2,B2,C2,C1,C,這一遞歸調用順序,決定了各個中間件處理的一些特色:

一、最早進行流程處理的中間件,其process_request()(若是存在的話)最早被執行,可是其process_response()(若是存在的話)卻最後獲得處理。

二、最後進行流程處理的中間件,其process_request()(若是存在的話)最後被執行,可是其process_response()(若是存在的話)緊接着獲得處理。

三、在中間件處理流程中,若是出現某個中間件的process_request()返回了response,這種狀況一般是處理過程當中出現了異常狀況,該中間件後續的中間件再也不參與處理,直接調用該中間件的process_response()(若是存在的話),或者直接返回。

相關文章
相關標籤/搜索