一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語(yǔ)言編程技術(shù)及教程分享平臺(tái)!
分類導(dǎo)航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務(wù)器之家 - 腳本之家 - Python - 從請(qǐng)求到響應(yīng)過(guò)程中django都做了哪些處理

從請(qǐng)求到響應(yīng)過(guò)程中django都做了哪些處理

2021-03-25 08:57創(chuàng)宇前端 Python

這篇文章主要給大家介紹了關(guān)于從請(qǐng)求到響應(yīng)過(guò)程中django都做了哪些處理的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

前言

最近面試的時(shí)候,被面試官問(wèn)道一個(gè)問(wèn)題,就是 request.user 里面的 user 是怎樣得到的,這個(gè)問(wèn)題當(dāng)時(shí)沒(méi)有回答上來(lái),可以說(shuō)是非常的尷尬,所以趕快查了一些資料,看了一些源碼,特地來(lái)總結(jié)一下這個(gè)問(wèn)題。

要想回答為什么可以直接通過(guò) request.user 得到請(qǐng)求的用戶,應(yīng)該先來(lái)看看請(qǐng)求被處理以及如何返回響應(yīng)的流程。今天先總結(jié)一下 django 從請(qǐng)求到響應(yīng)都進(jìn)行了哪些過(guò)程。

WSGI

當(dāng)客戶端發(fā)送一次請(qǐng)求后,最先處理請(qǐng)求的實(shí)際上是 web 服務(wù)器就是我們經(jīng)常說(shuō)的 nginx、Apache 這類的 web 服務(wù)器,而 WSGI 的作用就是把 web 服務(wù)器和 web 框架 (Django) 連接起來(lái)。WSGI 被分為了兩個(gè)部分:服務(wù)端和應(yīng)用端。為了處理一個(gè) WSGI 的響應(yīng),服務(wù)端執(zhí)行應(yīng)用程序并向應(yīng)用端提供一個(gè)回調(diào)函數(shù),應(yīng)用端處理請(qǐng)求并使用提供的回調(diào)將響應(yīng)返回給服務(wù)端。

本質(zhì)上來(lái)講,我覺(jué)得 WSGI 就是 web 服務(wù)器和 django 應(yīng)用之間的一個(gè)聯(lián)系人。

數(shù)據(jù)流

當(dāng)用戶向你的應(yīng)用發(fā)送一個(gè)請(qǐng)求的時(shí)候,一個(gè) WSGI handler 將會(huì)被初始化,它會(huì)完成以下工作:

  1. 導(dǎo)入 settings.py 和 django 的異常類
  2. 使用 load_middleware 方法加載 settings.py 中 MIDDLEWARE_CLASSES 或者 MIDDLEWARES 元組中所用的 middleware classes.
  3. 創(chuàng)建四個(gè)列表 (_request_middleware,_view_middleware, _response_middleware, _exception_middleware),里面分別包含處理 request,view,response 和 exception 的方法。
  4. WSGI Handler 將實(shí)例化一個(gè) django.http.HTTPRequest 對(duì)象的子類,django.core.handlers.wsgi.WSGIRequest.
  5. 循環(huán)遍歷處理 request 的方法 (_request_middleware 列表),并按照順序調(diào)用他們
  6. 解析請(qǐng)求的 url
  7. 循環(huán)遍歷每個(gè)處理 view 的方法 (_view_middleware 列表)
  8. 如果找的到的話,就調(diào)用視圖函數(shù)
  9. 處理任何異常的方法 (_exception_middleware 列表)
  10. 循環(huán)遍歷每個(gè)處理響應(yīng)的方法 (_response_middleware 列表),(從內(nèi)向外,與請(qǐng)求中間件的順序相反)
  11. 最后得到一個(gè)響應(yīng),并調(diào)用 web server 提供的回調(diào)函數(shù)

中間件

中間件被用在了 django 的許多關(guān)鍵功能中:例如,使用 CSRF 中間鍵來(lái)防止跨站請(qǐng)求偽造攻擊。它們也被用來(lái)處理會(huì)話數(shù)據(jù),身份認(rèn)證和授權(quán)同樣是由中間件來(lái)完成的。我們也可以自己編寫中間件來(lái)調(diào)整或者(短路)通過(guò)應(yīng)用程序的數(shù)據(jù)流。

django 的中間件至少含有以下四個(gè)方法中的一個(gè):process_request, process_response, process_view, process_exception。這些方法會(huì)被 WSGI handler 收集并按照順序調(diào)用。

process_request

我們可以先來(lái)看看 django.contrib.auth.middleware.AuthenticationMiddleware:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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))

這里我們可以發(fā)現(xiàn) request.user 這個(gè)屬性是在 AuthenticationMiddleware 中產(chǎn)生的。這個(gè)我們稍后再說(shuō)。

這里我們可以發(fā)現(xiàn),這個(gè)中間件只有 process_request,說(shuō)明它只在 request 這一步處理流入和流出 django 應(yīng)用的數(shù)據(jù)流。這個(gè)中間件會(huì)首先驗(yàn)證會(huì)話中間件是否被使用,然后通過(guò)調(diào)用 get_user 函數(shù)來(lái)設(shè)置用戶。當(dāng) WSGI 處理程序迭代

process_request 方法列表的時(shí)候,它將會(huì)構(gòu)建這個(gè)最終會(huì)被傳遞給視圖函數(shù)的請(qǐng)求對(duì)象,并能夠使你引用 request.user。一些中間件沒(méi)有 process_request 方法,在這個(gè)階段,會(huì)被跳過(guò)。

process_request 應(yīng)該返回 None 或者 HTTPResponse 對(duì)象。當(dāng)返回 None 時(shí),WSGI handler 會(huì)繼續(xù)加載 process_request 里面的方法,但是后一種情況會(huì)短路處理過(guò)程并進(jìn)入 process_response 循環(huán)。

解析 url

當(dāng)所有的 process_request 被調(diào)用完之后,我們就會(huì)得到一個(gè)將被傳遞給視圖函數(shù)的 request 對(duì)象。當(dāng)這個(gè)事件發(fā)生之前,django 必須解析 url 并決定調(diào)用哪一個(gè)視圖函數(shù)。這個(gè)過(guò)程非常簡(jiǎn)單,只需要使用正則匹配即可。settings.py 中有一個(gè) ROOT_URLCONF 鍵來(lái)指定根 url.py,在這里會(huì)包含你所有 app 的 urls.py 文件。如果沒(méi)有匹配成功,將會(huì)拋出一個(gè)異常 django.core.urlresolvers.Resolver404, 這是 django.http.HTTP404 的子類。

process_view

到這一步之后 WSGI handler 知道了調(diào)用哪一個(gè)視圖函數(shù),以及傳遞哪些參數(shù)。它會(huì)再一次調(diào)用中間件列表里面的方法,這次是_view_middleware 列表。所有 Django 中間件的 process_view 方法將會(huì)被這樣聲明:

?
1
process_view(request, view_function, view_args, view_kwargs)

和 process_request 一樣,process_view 函數(shù)必須返回 None 或者 HTTPResponse 對(duì)象,使得 WSGI handler 繼續(xù)處理視圖或者'短路'處理流程并返回一個(gè)響應(yīng)。在 CSRF middleware 中存在一個(gè) process_view 的方法。作用是當(dāng) CSRF cookies 出現(xiàn)時(shí),process_view 方法將會(huì)返回 None, 視圖函數(shù)將會(huì)繼續(xù)的執(zhí)行。如果不是這樣,請(qǐng)求將會(huì)被拒絕,處理流程將會(huì)被'短路',會(huì)生成一個(gè)錯(cuò)誤的信息。

進(jìn)入視圖函數(shù)

一個(gè)視圖函數(shù)需要滿足三個(gè)條件:

  • 必須是可以調(diào)用的。這可以是基于函數(shù)的視圖或者是 class-based 的視圖(繼承自 View 并且使用 as_view() 方法來(lái)使它成為可調(diào)用的。這些方法的調(diào)用依賴 HTTP verb(GET, POST, etc))
  • 必須接受一個(gè) HTTPRequest 對(duì)象作為第一個(gè)位置參數(shù)。這個(gè) HTTPRequest 對(duì)象是被所有 process_request 和 process_view 中間件方法處理的結(jié)果。
  • 必須返回一個(gè) HTTPResponse 對(duì)象,或者拋出一個(gè)異常。就是用這個(gè) response 對(duì)象來(lái)開(kāi)啟 WSGI handler 的 process_view 循環(huán)。

process_exception

如果視圖函數(shù)拋出一個(gè)異常,Handler 將會(huì)循環(huán)遍歷_exception_middleware 列表,這些方法按照相反的順序執(zhí)行,從 settings.py 里面列出來(lái)的最后一個(gè)中間件到第一個(gè)。如果一個(gè)異常被拋出,處理過(guò)程將會(huì)被短路,其他的 process_exception 將不會(huì)被執(zhí)行。通常我們依賴 Djnago's BaseHandler 提供的異常處理程序,但是我們也可以使用自定義的異常處理中間件。

process_response

在這個(gè)階段,我們得到了一個(gè) HTTPResponse 對(duì)象,這個(gè)對(duì)象可能是 process_view 返回的,也可能是視圖函數(shù)返回的。現(xiàn)在我們將循環(huán)訪問(wèn)響應(yīng)中間件。這是中間件調(diào)整數(shù)據(jù)的最后的機(jī)會(huì)。執(zhí)行的順序是從內(nèi)向外執(zhí)行。

以 cache middleware 的 process_response 為例:它依賴于你的 app 里面的不同的狀態(tài)(緩存是否打開(kāi)或者關(guān)閉,是否在處理一個(gè)數(shù)據(jù)流),來(lái)決定是否緩存你的響應(yīng)。

注意

django 1.10 和之前版本的區(qū)別:

在舊版本的 MIDDLEWARE_CLASSES 中,就算一個(gè)中間件”短路”了執(zhí)行過(guò)程,所有的中間件都會(huì)調(diào)用它們的 process_response 方法。而在新的 MIDDLEWARES 版本中,只有這個(gè)中間件和在它之前執(zhí)行的中間件才會(huì)調(diào)用 process_response 方法。

總結(jié)

以上就是 django 在處理一個(gè)請(qǐng)求的基本的過(guò)程,最后 django 的 WSGI Handler 會(huì)創(chuàng)建一個(gè)來(lái)自 HTTPResponse 的返回值,而且會(huì)調(diào)用回調(diào)函數(shù)把數(shù)據(jù)傳遞給 web server, 最后返回給用戶。

以下是兩個(gè)關(guān)鍵點(diǎn):

我們現(xiàn)在知道了視圖函數(shù)是如何和 url 解析器匹配以及什么在調(diào)用它 (WSGI Handler)

有四個(gè)關(guān)鍵的地方可以讓你掛鉤到請(qǐng)求 / 響應(yīng)周期:process_request, process_response, process_view, process_exception。請(qǐng)求中間件是從外部向內(nèi)執(zhí)行,最后抵達(dá)到視圖函數(shù),然后通過(guò)響應(yīng)中間件從內(nèi)向外返回。

參考資料

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)服務(wù)器之家的支持。

原文鏈接:https://juejin.im/post/5a6951cdf265da3e591e782d

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 亚洲天堂免费观看 | 亚洲精品无码不卡在线观看 | 日韩一级片在线免费观看 | 三体动漫在线观看免费完整版2022 | 亚洲欧美激情日韩在线 | 天天天做天天天天爱天天想 | 99久久精品国产综合一区 | 天天综合亚洲 | 小黄鸭YELLOWDUCK7596 | 99资源站 | 欧美成狂野欧美在线观看 | 貂蝉沦为姓奴小说 | 日本另类z0zx高清 | 久草在在线免视频在线观看 | 十大免费b2b网站 | 国产高清视频免费最新在线 | 日韩精品欧美国产精品亚 | 奇米社区 | 欧美多gayxxxx | 毛片免费视频观看 | 国产精品一区二区久久不卡 | 亚洲男人的天堂网 | 久久永久免费视频 | 青青草原在线 | 国产馆在线观看免费的 | 国产福利在线免费观看 | 草莓视频首页 | 国产91短视频 | 操碰91| 91粉色视频在线导航 | 九九热在线观看视频 | 91久久青青青国产免费 | 成人高辣h视频一区二区在线观看 | 亚洲经典| 大陆国产精品视频 | 国产a免费 | 波多野结衣之高校教师 | 天堂va在线高清一区 | 热久久最新视频 | 四虎精品成人免费影视 | 青青草国产精品久久久久 |