Django的中間件以及Request/Response循環(huán)

Django的中間件以及Request/Response循環(huán)

前言:萌新的疑問

在建立一個新的Django項目時,你要做的第一件事就是連接你的URLconf并設(shè)置一些視圖。 但是這里真的發(fā)生了什么? Django如何將流量路由到視圖,中間件在這個周期中扮演什么角色?
我以前眼中的Django:

image

WSGI

WSGI是為解決一個基本問題而創(chuàng)建的工具:將Web服務器連接到Web框架。 WSGI有兩個方面:'服務器'方面和'應用程序'方面。 為了處理WSGI響應,服務器執(zhí)行應用程序,并向應用程序端提供回調(diào)函數(shù)。 應用程序處理請求并使用提供的回調(diào)將響應返回給服務器。 本質(zhì)上,WSGI處理程序充當您的Web服務器(Apache,NGINX等)和您的Django項目之間的守門員。

服務器和應用程序之間是中間件。 您可以將中間件視為一系列雙向過濾器:它們可以改變(或短路)在網(wǎng)絡(luò)和Django應用程序之間來回傳輸?shù)臄?shù)據(jù)。

整個Django的執(zhí)行過程:數(shù)據(jù)流

當用戶請求你的應用程序時,WSGI處理程序被實例化,然后Django按照順序處理以下環(huán)節(jié):

  1. 導入你的settings.py文件和Django的異常類。
  2. 加載它在位于settings.py中的MIDDLEWARE_CLASSES或者。MIDDLEWARES(取決于Django版本)元組中找到的所有中間件類。
  3. 構(gòu)建處理 request,view, responseexception的四個方法列表。
  4. 通過請求方法循環(huán),按順序運行它們。
  5. 解決了所請求的URL。
  6. 循環(huán)每個視圖處理方法。
  7. 調(diào)用視圖函數(shù)(通常是渲染模板)。
  8. 處理任何異常方法。
  9. 循環(huán)遍歷每個響應方法(從內(nèi)向外,從請求中間件的相反順序)。
  10. 最后建立一個返回值并調(diào)用web服務器的回調(diào)函數(shù)。

中間件

中間件被用在Django項目中的許多關(guān)鍵功能中:例如,使用CSRF中間件來防止跨站請求偽造攻擊。 他們用來處理會話數(shù)據(jù)。 身份驗證和授權(quán)是使用中間件完成的。 您可以編寫自己的中間件類來通過應用程序調(diào)整(或短路)數(shù)據(jù)流。

image

process_request

Django中間件必須至少包含以下方法之一:process_requestprocess_response,process_viewprocess_exception。 這些是由WSGI處理程序收集的方法,然后按列出的順序調(diào)用。 讓我們快速瀏覽django.contrib.auth.middleware.AuthenticationMiddleware,這是運行django-admin.py startproject時默認安裝的中間件之一:

def get_user(request):
    if not hasattr(request, '_cached_user'):
        request._cached_user = auth.get_user(request)
    return request._cached_user


class AuthenticationMiddleware(MiddlewareMixin):
    def process_request(self, request):
        assert hasattr(request, 'session'), (
              "The Django authentication middleware requires session middleware "
              "to be installed. Edit your MIDDLEWARE%s setting to insert "
              "'django.contrib.sessions.middleware.SessionMiddleware' before "
              "'django.contrib.auth.middleware.AuthenticationMiddleware'."
        ) % ("_CLASSES" if settings.MIDDLEWARE is None else "")
        request.user = SimpleLazyObject(lambda: get_user(request))

正如你所看到的,這個中間件只能處理來自Django應用程序的數(shù)據(jù)流的“請求”步驟。 該中間件首先驗證會話中間件是否已經(jīng)被使用,然后通過調(diào)用get_user幫助函數(shù)來設(shè)置用戶。 當WSGI處理程序迭代process_request方法列表時,它會構(gòu)建這個請求對象,最終將被傳遞到視圖中,并且您將能夠引用request.user。 settings.py中有一些中間件沒有有process_request方法。 不過沒關(guān)系,在這個階段剛剛被跳過。

process_request應該返回None(如本例),或者可以返回一個HttpResponse對象。 在前一種情況下,WSGI處理程序?qū)⒗^續(xù)處理process_request方法,后者將“短路”進程并開始process_response循環(huán)。【如上圖所示,跳過view過程,直接去response】

Resolve the URL(解析URL)

現(xiàn)在process_request方法已經(jīng)被調(diào)用了,現(xiàn)在我們有一個請求對象將被傳遞給視圖。在此之前,Django必須解析URL并確定調(diào)用哪個視圖函數(shù)。這只是通過正則表達式匹配來完成的。您的settings.py將會有一個名為ROOT_URLCONF的鍵,它表示“root”urls.py文件,您將從中為每個應用程序添加urls.py文件。 URL路由在Django教程中已經(jīng)非常廣泛地介紹了,所以在這里就不需要了。

一個觀點有三個要求:

  1. 它必須是可調(diào)用的。它可以是基于函數(shù)的視圖,也可以是繼承自基于類的視圖。根據(jù)HTTP動作(GET,POST等)查看as_view() 方法以使其可調(diào)用。
  2. 它必須接受一個HttpRequest對象作為第一個位置參數(shù)。這是調(diào)用所有process_request和process_view中間件方法的結(jié)果。
  3. 它必須返回一個HttpResponse對象,或引發(fā)一個異常。這是用于啟動WSGI處理程序的process_view循環(huán)的響應對象。

process_view

現(xiàn)在WSGI處理程序知道要調(diào)用哪個視圖函數(shù),它再次遍歷其中間件方法列表。 任何Django中間件的process_view方法都是這樣聲明的:

process_view(request,view_function,view_args,view_kwargs)

和process_request一樣,process_view函數(shù)必須返回None或HttpResponse對象(或引發(fā)異常),從而允許WSGI處理程序繼續(xù)處理視圖或“短路”并返回響應。 查看CSRF中間件的源代碼,查看process_view的實例。如果存在CSRF cookie,那么process_view方法將返回None并執(zhí)行視圖。 如果不是,請求被拒絕,并且進程被短路,導致失敗消息。

process_exception

如果view函數(shù)產(chǎn)生一個異常,Handler將遍歷它的process_exception方法列表。 這些方法以相反的順序執(zhí)行,從settings.py中列出的最后一個中間件到第一個。 如果發(fā)生異常,則進程將短路,并且不會調(diào)用其他進程中斷件。 通常我們依靠Django的BaseHandler提供的異常處理程序,但是在編寫自己的定制中間件類時,您當然可以實現(xiàn)自己的異常處理。

process_response

在這一點上,我們將有一個HttpResponse對象,可以是由視圖或由WSGI處理程序構(gòu)建的process_view方法列表返回的,也可以輪流循環(huán)訪問響應中間件。這是任何中間件都必須修改數(shù)據(jù)的最后機會,并且是從內(nèi)層向外執(zhí)行的(想象一下洋蔥,視圖在中心)。看一下緩存中間件源代碼中的process_response實例:取決于應用程序中的不同條件(即緩存是否關(guān)閉,如果我們正在處理流等),我們需要響應存儲在緩存中還是不存在。

注意:在1.10之前的Django和更高版本之間的一個區(qū)別是:在舊式MIDDLEWARE_CLASSES中,即使較早的中間件使進程短路,每個中間件也將始終調(diào)用其process_response方法。在新的MIDDLEWARES風格中,只有中間件和之前執(zhí)行的中間件才會調(diào)用其process_response方法。有關(guān)MIDDLEWARES和MIDDLEWARE_CLASSES之間差異的更多詳細信息,請參閱文檔。

好了~

最后,Django的WSGI Handler從HttpResponse對象構(gòu)建一個返回值,并執(zhí)行回調(diào)函數(shù)將該數(shù)據(jù)發(fā)送到Web服務器并發(fā)送給用戶。

所以,兩個關(guān)鍵要點:

  1. 現(xiàn)在我們知道view函數(shù)是如何與URLconf相匹配的,以及實際調(diào)用的是什么(WSGI Handler)。
  2. 有四個關(guān)鍵點可以通過您自己的定制中間件進入請求/響應循環(huán):process_request,process_response,process_view和process_exception。 想一想:請求中間件是從外部執(zhí)行的,在中心點擊查看,然后通過響應中間件返回到表面。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • Refer to: www.threemeal.com/blog/12/ 中間件 中間件是一個鉤子框架,它們可以介...
    蘭山小亭閱讀 16,757評論 9 164
  • 目錄 一、中間件簡介 在django中,中間件其實就是一個類,在請求到來和結(jié)束后,django會根據(jù)自己的規(guī)則在合...
    CaiGuangyin閱讀 882評論 0 3
  • Django 文檔協(xié)作翻譯小組人手緊缺,有興趣的朋友可以加入我們,完全公益性質(zhì)。交流群:467338606網(wǎng)站:h...
    布客飛龍閱讀 859評論 0 37
  • 中間件是一個鉤子框架,它們可以介入Django 的請求和響應處理過程。它是一個輕量級、底層的“插件”系統(tǒng),用于在全...
    低吟淺唱1990閱讀 578評論 0 0
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,506評論 19 139

友情鏈接更多精彩內(nèi)容