2023-04-23 21:23:08來源:博客園
本文首發(fā)于公眾號:Hunter后端原文鏈接:Django筆記二十九之中間件介紹
(資料圖片僅供參考)
這一節(jié)介紹一下 Django 的中間件。
關(guān)于中間件,官方文檔的解釋為:中間件是一個嵌入 Django 系統(tǒng)的 request 和 response 的鉤子框架,是一個能夠全局改變 Django 輸入/輸出的系統(tǒng)。
我們可以這樣理解,一個 request 請求發(fā)送到 Django 系統(tǒng)的過程中,在經(jīng)過路由和視圖的處理前,會先經(jīng)過一層處理,這個處理操作可以是日志記錄,可以是登錄驗證甚至你想在系統(tǒng)里定義的功能,這個操作就是中間件實現(xiàn)的功能。
接下來我們將通過一個記錄請求的 ip 的功能的介紹來介紹一下中間件的實現(xiàn)流程。
以下是本篇筆記目錄:
請求經(jīng)過 Django 然后返回的流程HttpRequest 和 HttpResponse 介紹中間件的示例介紹記錄訪問 ip 的功能實現(xiàn)1、請求經(jīng)過 Django 然后返回的流程首先,前端發(fā)起一個請求,這個請求經(jīng)由 web 服務(wù)器轉(zhuǎn)發(fā)給 Django 系統(tǒng),在進(jìn)入 Django 系統(tǒng)后會先經(jīng)過一系列的中間件的功能處理。
這個中間件會在 settings.py 里定義,Django 系統(tǒng)默認(rèn)自帶的中間件列表如下:
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",]
這些中間件我們也可以根據(jù)自己的需求自己定義,比如新加一個登錄權(quán)限,或者日志記錄,或者對輸入的參數(shù)進(jìn)行格式化處理也可以,或者自己想要設(shè)置的其他功能也行,具體怎么設(shè)置在后面介紹。
在中間件處理的流程中,請求會被按照順序從上往下處理。
這個流程過后,一個 request 請求才會被進(jìn)行 URL 的路徑匹配,如果匹配上,再去找相應(yīng)的 views 視圖函數(shù)進(jìn)行數(shù)據(jù)處理
views 處理完之后,會形成一個 response,返回,然后再次經(jīng)歷這個中間件處理,因為在每一層中間件中都類似于一種嵌套,所以返回 response 的時候,是從下往上再次處理 response 的。
中間件處理結(jié)束之后再被返回出去,給到前端。
在這整個流程處理中,可以說中間件是進(jìn)行了兩次操作,一個是進(jìn)入的時候處理 request,一個是返回的時候處理 response。
2、HttpRequest 和 HttpResponse 介紹我們先來看一個視圖函數(shù):
def time_view(request): now = datetime.datetime.now() html = "now: %s
abc\nabc" % now return HttpResponse(html)
當(dāng) Django 接收到一個請求,系統(tǒng)會創(chuàng)建一個 HttpRequest 對象,這個對象就是上面的視圖函數(shù)里的輸入?yún)?shù),request
在對數(shù)據(jù)進(jìn)行處理后,系統(tǒng)會返回一個 HttpResponse 對象,這個就是我們 return 的內(nèi)容。
在一個 HttpRequest 對象里,會包含請求的路徑、參數(shù)、請求方式、 cookie 等一切請求過來時的數(shù)據(jù),我們可以在請求的時候根據(jù)需要存取。
在返回的 HttpResponse 中,可以是一個 html 頁面,也可以是 json 格式的數(shù)據(jù),內(nèi)容是可以自定義的,只要前端可以做相應(yīng)的處理。
3、中間件的示例介紹接下來我們定義一個中間件,結(jié)構(gòu)大致如下:
# huter/middleware.pyclass SimpleMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): # 在請求進(jìn)入視圖函數(shù)前的可以執(zhí)行一些操作,針對 request print(request.path) response = self.get_response(request) # 在處理完請求后,可以執(zhí)行一些操作,針對 response # log_response_info() return response
然后我們在 sttings.py 里引入這個中間件,我們放到 MIDDLEWARE 列表的最下面,說明這個中間件會在其他中間件處理完 request 之后再處理:
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", "hunter.middleware.TestMiddleware",]
在 SimpleMiddleware 這個類里,call() 函數(shù)會自動調(diào)用,其中有一行,response = self.get_response(request)
在這一行函數(shù)之前,可以對請求的 request 做處理,包括我們前面說的各種功能,比如日志、登錄驗證、參數(shù)格式化等
在這一行函數(shù)之后,獲取了 response,這個就是視圖函數(shù)返回的 HttpResponse,我們可以在這里對它的 response.status_code 狀態(tài)碼,和 response.content 做處理
比如前面 time_view 函數(shù)返回的內(nèi)容是一個 JsonResponse:
return JsonResponse({"code": 0})
那么在這里我們可以獲取然后處理這個 HttpResponse:
def __call__(self, request): response = self.get_response(request) content = json.loads(response.content) content["msg"] = "success" response.content = json.dumps(content) return response
這里只是一個示例,因為并不是所有的 HttpResponse 都是 json 格式的數(shù)據(jù),所以可能需要加一個 try except 做下處理
還有一個功能是我之前做過的,就是在 headers 中加一個特定的字符串,表示是我們系統(tǒng)專有的,用于前端判斷,這個很簡單,就是在 response 的 headers 參數(shù)中加一個鍵值對:
response.headers["system"] = "hunter"
以上就是一個最簡單的中間件的處理方式。
process_view
除了 call函數(shù)以外,還有一個 process_view() 的函數(shù)
這個函數(shù)是在 Django 系統(tǒng)調(diào)用 views 視圖函數(shù)前被調(diào)用,它的返回值是 None 或者一個 HttpResponse
如果為 None,那么系統(tǒng)會接著調(diào)用視圖函數(shù),如果是 HttpResponse 作為返回值,說明系統(tǒng)在這里已經(jīng)處理了請求,不需要再走views視圖函數(shù),然后就會直接返回。
我們通過下面的例子來解釋這個函數(shù)作用。
4、記錄訪問 ip 的功能實現(xiàn)假設(shè)我們需要禁止某一個或者某一個 ip 列表的請求訪問我們的系統(tǒng)
當(dāng)然,這個操作,在 web 服務(wù)器那部分就可以攔截,這里就是單純舉個例子
那么我們這樣設(shè)置一個 process_view 的功能,在真正執(zhí)行視圖函數(shù)(也就是url 匹配上的 view函數(shù))前,取出這個 request 的訪問的ip,然后進(jìn)行判斷,如果在 禁止列表,那么則直接返回一個禁止訪問的頁面。
class TestMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): response = self.get_response(request) return response def process_view(self, request, view_func, *view_args, **view_kwargs): EXCLUDE_IPS = ["192.168.1.54"] if "HTTP_X_FORWARDED_FOR" in request.META: ip = request.META["HTTP_X_FORWARDED_FOR"] else: ip = request.META["REMOTE_ADDR"] if ip in EXCLUDE_IPS: return HttpResponse("您的ip被禁止
") return None
在這里,我們拿到請求的 ip 地址,去和我們定義的禁止ip列表做比較
如果在禁用列表,則直接返回 HttpResponse,不接著請求我們的服務(wù)來
否則,就返回 None,系統(tǒng)接收到 None 之后,會接著往下處理。
如果想獲取更多后端相關(guān)文章,可掃碼關(guān)注閱讀:
責(zé)任編輯:標(biāo)簽:
本文首發(fā)于公眾號:Hunter后端原文鏈接:Django筆記二十九之中間件介紹這一節(jié)介紹一下Django的中間件。關(guān)于
商務(wù)部:發(fā)揮出口信保作用保障外貿(mào)主體發(fā)展,外貿(mào),融資,商務(wù)部,中小微,出口信保
4月23日,寧夏石嘴山市平羅縣以“閱讀新時代惠享新生活”為主題啟動2023年“塞上書香節(jié)”暨“繽紛塞上惠...
你需要的東西鋒利的刀子大平底鍋或荷蘭烤箱選擇的香草和調(diào)味料酸性液體的選擇水果(可選)蔬菜(可選)即時
法國示威者在高速路上攪水泥砌墻今天的熱度非常高,現(xiàn)在也是在熱搜榜上了,那么具體的法國示威者在高速路上