Django系列 1:請(qǐng)求的生命周期

p

進(jìn)入本文之前,首先請(qǐng)大家先看該篇博客,對(duì)你開(kāi)始本文的理解有一定的幫助:

Django系列之啟動(dòng)入口源碼分析

Django 源碼分析:?jiǎn)?dòng)過(guò)程

一個(gè)請(qǐng)求request 經(jīng)過(guò)瀏覽器, nginx轉(zhuǎn)發(fā),uwsgi服務(wù)器,再到我們的應(yīng)用服務(wù)器,這一過(guò)程我們暫且先跳過(guò)去,因?yàn)槲覀円芯康氖且粋€(gè)請(qǐng)求request進(jìn)入到應(yīng)用服務(wù)器后, 如何匹配到視圖類的(CBV)的,進(jìn)入視圖函數(shù)前干了什么, 出了視圖函數(shù)干了什么,進(jìn)入之前與出去之后都經(jīng)過(guò)哪些中間件,這些是我們著重要研究的地方。

1:任何一個(gè)應(yīng)用 application,他必須是可調(diào)用的(callable), 因?yàn)檫@是request的入口。源碼位置在Django中的位置如下所示:

2:所有的request都會(huì)進(jìn)入run方法:

進(jìn)入run方法以后, 就會(huì)獲取應(yīng)用的application:

3:前面說(shuō)過(guò)django中的application是一個(gè)可調(diào)用對(duì)象,那么application對(duì)應(yīng)的類就是:django.contrib.staticfiles.handlers:StaticFilesHandler 實(shí)例

最后調(diào)用父類的的方法:django.core.handlers.wsgi:WSGIHandler,至此我們已經(jīng)知道所有的request在django框架中的入口處。

好了, 現(xiàn)在我們已經(jīng)知道每個(gè)請(qǐng)求的入口是WSGIHandler.__call__函數(shù), name在這個(gè)函數(shù)最重要的就是這句代碼?response =self.get_response(request)

那我們現(xiàn)在看看這句代碼的背后都干了什么,重點(diǎn)在這句:self._middleware_chain(request),它在項(xiàng)目啟動(dòng)后會(huì)將所有的中間件形成一個(gè)鏈,在鏈的最開(kāi)始就是配置中MIDDLEWARE第一個(gè)中間件。

在load_middleware方法中,get_response最初是self._get_response方法(即:最初的handler就是get_response),通過(guò)循環(huán)每次handler改變, 第一次循環(huán)后handler就是MIDDLEWARE最后一個(gè)中間件的實(shí)例,一直到循環(huán)結(jié)束,那么handler就是第一個(gè)中間件的是實(shí)例;

當(dāng)代碼執(zhí)行到:

self._middleware_chain(request)

當(dāng)所有的中間件都執(zhí)行完畢后,最后執(zhí)行WSGIHandler的_get_response方法(如下圖), 該方法包括了,請(qǐng)求解析(找到正確的視圖類),視圖函數(shù)中間件,從wrapped_callback分派執(zhí)行請(qǐng)求方法(get()、post()、........),template中間件、exception中間件,最后又會(huì)執(zhí)行所有中間件的process_response方法

所以一個(gè)請(qǐng)求到達(dá)應(yīng)用服務(wù)器后的流程就是:

(1):request 找到應(yīng)用服務(wù)器 __call__(self, environ, start_response) 方法,并執(zhí)行 response = self.get_response(request) 方法。

(2):request 進(jìn)入?self.get_response(request) 方法后,最重要的就是執(zhí)行了該句代碼:response = self._middleware_chain(request)

(3):中間件鏈 self._middleware_chain(request) 具體干了這么幾件事:

? ? ? ? ? ? (a):? 順序執(zhí)行中間件實(shí)例的 process_request 方法,如果該方法有返回值?response 實(shí)例, 那么不會(huì)執(zhí)行后續(xù)的中間件, 而是逆序執(zhí)行中間件的?process_response 方法,最后返回服務(wù)器直至瀏覽器

? ? ? ? ? ? (b):? ?當(dāng)所有的?process_request 方法執(zhí)行完畢后,執(zhí)行?WSGIHandler._get_response(self, request) 方法,根據(jù)請(qǐng)求的path解析到正確的視圖函數(shù)或視圖類(即該方法的 callback或 wrapped_callback)

? ? ? ? ? ? (c):? ?執(zhí)行所有的模板中間件

? ? ? ? ? ? (b):??執(zhí)行所有的異常中間件

? ? ? ? ? ? (d):? 最后逆序執(zhí)行中間件實(shí)例的? ?process_response 方法,該方法必須返回一個(gè)?response 實(shí)例 , 最后相應(yīng)返回給wsgi或uwsgi 這樣發(fā)服務(wù)器,由他們返回瀏覽器等前端

那么整個(gè)請(qǐng)求的過(guò)程就是在這些過(guò)程中完成的,django框架的核心就是圍繞這些流程逐步拓展,請(qǐng)求解析、模板與響應(yīng)、異常處理等等。

最后補(bǔ)充一張圖,關(guān)于請(qǐng)求穿過(guò)中間件的順序:


中間件順序的參考:中間件順序


def? process_request(self, request):? pass

def process_view(self, request, callback, callback_args, callback_kwargs):? pass

def?process_template_response(self, request,?response):? pass

def process_exception(self, request, exception):? pass

def process_response(self, request, response):? pass


(1): 在各個(gè)中間件的 process_request 均沒(méi)有異常且返回值是None, 那么下一步再按照中間件的順序依次執(zhí)行各自的 process_view, 如果process_view 返回值均是None, 下一步再按照中間件逆序方向從下往上執(zhí)行process_response? ,直至第一個(gè)中間件的process_response? (如黑線箭頭流程所示)

(2):如果執(zhí)行的某個(gè)中間件的 process_request 返回值是HttpResponse 對(duì)象,那么直接執(zhí)行該中間件的?process_response,再按照中間件的逆序方向從下往上執(zhí)行其它的 process_response?? (如紅線箭頭流程所示)

(3):在各個(gè)中間件的 process_request 均沒(méi)有異常且返回值是None, 那么下一步再按照中間件的順序依次執(zhí)行各自的 process_view, 如果在某個(gè)中間件的process_view 返回值是?HttpResponse 對(duì)象,那么直接逆序執(zhí)行各個(gè)中間件的?process_response (從下到上)(如藍(lán)線箭頭流程所示)

(4):如果在某個(gè)中間件的 process_request 發(fā)生異常,那么會(huì)直接該中間件的process_response?(從下到上),然后逆序執(zhí)行其它中間的?process_response? 方法(該中間件的process_response? 不會(huì)執(zhí)行),直到結(jié)束?(如黑線箭頭流程所示)

(5):如果在某個(gè)中間件的 process_view 發(fā)生異常,那么會(huì)直接該中間件的?process_response??(從下到上),然后逆序執(zhí)行其它中間的??process_response? 方法(該中間件的?process_response? 會(huì)執(zhí)行),直到結(jié)束??(如藍(lán)色線箭頭流程所示)

(6):如果執(zhí)行到視圖函數(shù) view 中發(fā)生異常,?那么會(huì)依次執(zhí)行各中間件的?process_exception(從下到上),然后逆序執(zhí)行其它各個(gè)中間的??process_response? 方法,直到結(jié)束??(如紅色線箭頭流程所示)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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