Django的一次請求到響應的流程

王海波發表於2016-05-26

Django的請求到響應的處理流程本質上差不多,簡單來說,都是利用WSGI,針對request,進行response。當然在響應前會傳送request_started訊號,會呼叫預處理函式(在Flask中是before_request,Django是請求中介軟體,process_request),響應完成後會傳送request_finished函式,呼叫響應後函式(在Flask中是after_request中,Django中是process_response)。思想差不多,但是處理細節上還是有很多不同的。

  1. 使用者瀏覽器一個url,發起一個請求

在Web應用啟動後,會生成一個 WSGIHandler 例項(根據setting中的WSGI_APPLICATION = ‘dailyblog.wsgi.application’ 呼叫函式),每次請求響應都用這個例項。 settings 裡設定了 WSGI application。 返回例項程式碼:

WSGIHandler繼承自BaseHander。這個處理器會匯入專案中的 settings模組、匯入 自定義例外類,最後呼叫自己的 load_middleware 方法,載入所有列在 MIDDLEWARE_CLASSES 中的 middleware 類並且內省它們。

BaseHander部分原始碼:

請注意,只有第一次請求時會呼叫 load_middleware,以後不再呼叫了。
其中,request_middleware、view_middleware 是順序,template_response_middleware、response_middleware、exception_middleware 是逆序。

一 個 middleware 類可以包括請求響應過程的四個階段:request,view,response 和 exception。對應的方法:process_request,process_view, process_response 和 process_exception。我們在middleware中介軟體中定義其中的方法。

3、構造WSGIRequest。
WSGIHandler 處理器準備工作已經完成,隨後它給排程程式傳送一個訊號 request_started(這個和Flask中的request_started訊號差不多),然後根據入 environ 構造 WSGIRequest 物件,它的父類是HttpRequest。

4、 處理Middleware的request中介軟體
WSGIHander的get_response方法處理 _request_middleware 例項變數並呼叫其中的每一個方法,傳入 HttpRequest 的例項作為引數,即請求到達Request Middlewares,中介軟體對request做一些預處理,如果中介軟體返回response,會直接響應請求。

5、 URLConf通過urls.py檔案和請求的URL找到相應的檢視函式

此時會建立django.core.urlresolvers.RegexURLResolver 的一個例項。

URLresolver 遵循一個相當簡單的模式。對於在 URL 配置檔案中根據 ROOT_URLCONF 的配置產生的每一個在 urlpatterns 列表中的條目,它會檢查請 求的 URL 路徑是否與這個條目的正規表示式相匹配,如果是的話,有兩種選擇:

  1. 如果這個條目有一個可以呼叫的 include,resolver 擷取匹配的 URL,轉 到 include 指定的 URL 配置檔案並開始遍歷其中 urlpatterns 列表中的 每一個條目。根據你 URL 的深度和模組性,這可能重複好幾次。
  2. 否則,resolver 返回三個條目:匹配的條目指定的 view function;一個 從 URL 得到的未命名匹配組(被用來作為 view 的位置引數);一個關鍵 字引數字典,它由從 URL 得到的任意命名匹配組和從 URLConf 中得到的任 意其它關鍵字引數組合而成。

注意這一過程會在匹配到第一個指定了 view 的條目時停止,因此最好讓你的 URL 配置從複雜的正則過渡到簡單的正則,這樣能確保 resolver 不會首先匹配 到簡單的那一個而返回錯誤的 view function。

如果沒有找到匹配的條目,resolver 會產生 django.core.urlresolvers.Resolver404 異常,它是 django.http.Http404 例 外的子類。後面我們會知道它是如何處理的。

6、 開始呼叫View中相應的檢視函式或基於類的檢視。

7、View進行一些處理,如通過模型Models返回資料。

8、如果需要,Views可以建立一個額外的Context,Context被當做變數傳給Template。

9、Template渲染輸出

10、渲染後的輸出被返回到View

11、HTTPResponse被髮送到Response Middlewares

12、Response Middlewares對response進行特定的處理,然後返回一個新的response

13、Response返回呈現給使用者

14、一旦 middleware完成了最後環節,處理器將傳送一個訊號 request_finished,訂閱這個訊號的事件會清空並釋放任何使用中的資源。比如,Django 的 request_finished 的訂閱者subscriber會關閉所有資料庫連線。

15、所有流程至此已經全部完成。

下面是處理器的原始碼:

異常情況:

如果 view 函式,或者其中的什麼東西,發生了異常,那麼 get_response將遍歷它的 _exception_middleware 例項變數並呼叫那裡的每個方法,傳入 HttpResponse 和這個 exception 作為引數。如果順利,最後會例項化,並返回一個 HttpResponse 。

這時候有可能還是沒有得到一個 HttpResponse,這可能有幾個原因:

  1. view 並沒有返回內容。
  2. view 可能丟擲了異常,但middleware沒有 能處理它。
  3. 一個 middleware 方法試圖處理一個異常時,自己又產生了一個異常。

處理器會做些相應的異常處理,如404,403,500等等,具體可以看上面的原始碼。

裡面有些地方是參考其他部落格文章,但忘了地址了。如有原作者看到,請給予提示,謝謝。

打賞支援我寫出更多好文章,謝謝!

打賞作者

打賞支援我寫出更多好文章,謝謝!

任選一種支付方式

Django的一次請求到響應的流程 Django的一次請求到響應的流程

相關文章