Django中間件執行順序

中間件

Django中的中間件是一個輕量級、底層的插件系統,能夠介入Django的請求和響應處理過程,修改Django的輸入或輸出。中間件的設計爲開發者提供了一種無侵入式的開發方式,加強了Django框架的健壯性。python

咱們可使用中間件,在Django處理視圖的不一樣階段對輸入或輸出進行干預。django

1 中間件的定義方法

定義一箇中間件工廠函數,而後返回一個能夠別調用的中間件。session

中間件工廠函數須要接收一個能夠調用的get_response對象。閉包

返回的中間件也是一個能夠被調用的對象,而且像視圖同樣須要接收一個request對象參數,返回一個response對象。框架

def simple_middleware(get_response):
    # 此處編寫的代碼僅在Django第一次配置和初始化的時候執行一次。

    def middleware(request):
        # 此處編寫的代碼會在每一個請求處理視圖前被調用。

        response = get_response(request)

        # 此處編寫的代碼會在每一個請求處理視圖以後被調用。

        return response

    return middleware

例如,在users應用中新建一個middleware.py文件,函數

def my_middleware(get_response):
    print('init 被調用')
    def middleware(request):
        print('before request 被調用')
        response = get_response(request)
        print('after response 被調用')
        return response
    return middleware

定義好中間件後,須要在settings.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',
    'users.middleware.my_middleware',  # 添加中間件
]

定義一個視圖進行測試插件

def demo_view(request):
    print('view 視圖被調用')
    return HttpResponse('OK')

執行結果設計

注意:Django運行在調試模式下,中間件init部分有可能被調用兩次。調試

2 執行流程

3 多箇中間件的執行順序

  • 在請求視圖被處理前,中間件由上至下依次執行
  • 在請求視圖被處理後,中間件由下至上依次執行

示例:

定義兩個中間件

def my_middleware(get_response):
    print('init 被調用')
    def middleware(request):
        print('before request 被調用')
        response = get_response(request)
        print('after response 被調用')
        return response
    return middleware

def my_middleware2(get_response):
    print('init2 被調用')
    def middleware(request):
        print('before request 2 被調用')
        response = get_response(request)
        print('after response 2 被調用')
        return response
    return 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',
    'users.middleware.my_middleware',  # 添加
    'users.middleware.my_middleware2',  # 添加
]

執行結果  

init2 被調用
init 被調用
before request 被調用
before request 2 被調用
view 視圖被調用
after response 2 被調用
after response 被調用

總結:中間件的本質其實就是個裝飾器,對於裝飾器我以前的隨筆裏也詳細說過,裝飾器的本質其實就是個閉包

  對於裝飾器來講,在這裏程序從上到下執行,開始記錄裝飾器1-3,而後讀到了函數的時候,裝飾器開始裝飾,把函數的引用傳入裝飾器中,從裝飾器3開始往上裝飾,因此這時候開始執行裝飾器3的初始化,並把裝飾完的函數當作一個新的函數,再次把新的引用傳入到裝飾器2,接着裝飾器2進行初始化,再次把新的函數的引用傳入到裝飾器1進行裝飾,這時候裝飾器1的初始化開始,並開始執行,從而接下來的執行順序爲1-3執行裝飾的內容,最後再執行原本的函數,達到一個對原有函數增長功能和特性的要求。

裝飾器:從程序開始的順序,從上到下讀取----》從下到上裝飾----》從上到下執行

  在中間件中,執行順序等同,只不過中間件裝飾的是視圖函數或者是試圖類,會有一個init()初始化,爲了便於理解我在說明裝飾器順序的時候,那裏說的初始化就是如今的init(),也就是中間件在執行上也是從最接近函數或者類的中間件開始初始化,在中間件註冊時,若是有多箇中間件,程序按照從上到下的順序來確認中間件,接着執行視圖函數的時候,開始從下到上的進行init(),這裏的初始化init()相似於Flask框架裏四種請求勾子中的請求開始前執行一次的意思,從下到上執行完init後,再從上到下執行請求前所要執行的代碼(見上文),請求完成後再從下往上執行請求後的代碼(見上文)。

中間件:從程序開始的順序,從上到下讀取----》從下到上初始化init()----》從上到下執行請求前----》視圖的請求----》從下到上執行請求後

相關文章
相關標籤/搜索