您好,登錄后才能下訂單哦!
前言
我們可以給視圖函數加裝飾器來判斷是用戶是否登錄,把沒有登錄的用戶請求跳轉到登錄頁面等等。我們通過給幾個特定視圖函數加裝飾器實現了這個需求,但是以后添加的視圖函數可能也需要加上裝飾器,這樣是不是稍微有點繁瑣。
因此,我們可以使用更適宜的方式來實現類似給所有請求都做相同操作的功能了——中間件.
什么是中間件?
官方的說法:
==中間件是一個用來處理Django的請求和響應的框架級別的鉤子==。它是一個輕量、低級別的插件系統,用于在==全局范圍內==改變Django的輸入和輸出。每個中間件組件負責做一些特定的功能。
由于其影響的是全局,所以需要謹慎使用,==使用不當會影響性能==。
說的直白一點,中間件可以幫助我們==在視圖函數執行之前和執行之后做一些額外的操作==。
==它的本質是一個自定義類==,類中定義了幾個方法,Django框架會在請求的特定時間去執行這些方法。
打開Django項目的Settings.py文件,看到下圖的MIDDLEWARE配置項:
MIDDLEWARD配置項是一個列表,列表中是一個個字符串,這些字符串其實是一個個類,也就是一個個中間件。
自定義中間件
中間件可以定義五種方法,分別是:
以上方法的返回值可以是None,或者是一個HttpResponse對象,如果是None,則繼續按照django定義的規則向后繼續執行,如果是HttpResponse對象,則直接將改對象返回給用戶。
重點理解process_request 與 process_response.
***
示例
from django.utils.deprecation import MiddlewareMixin class MD1(MiddlewareMixin): def process_request(self, request): print("我是MD1的process_request方法") def process_response(self, request, response): print("我是MD1的process_response方法") return response class MD2(MiddlewareMixin): def process_request(self, request): print("我是MD2的process_request方法") def process_response(self, request, response): print("我是MD2的process_response方法") return response
在settings.py配置文件中的MIDDLEWARE配置項加上自定義的中間件:==app名稱.文件名.類名==
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', # 自定義中間件(注意順序) 'untitled01.my_middlewares.MD1', 'untitled01.my_middlewares.MD2', ]
中間件的五種方法
process_request
==執行時間:== 在視圖函數之前,在路由匹配之前 · ==參數:== request:請求對象,與視圖中用到的request參數是同一個對象 · ==返回值:== None:按照正常的流程走 HttpResponse:接著倒序執行當前中間件的以及之前執行過的中間件的process_response方法,不再執行其它的所有方法 · ==執行順序:== 按照MIDDLEWARE中的注冊的順序執行,也就是此列表的索引值
process_response
==執行時間:== 最后執行 · ==參數:== request:請求對象,與視圖中用到的request參數是同一個對象 response:響應對象,與視圖中返回的response是同一個對象 · ==返回值:== response:必須返回此對象,按照正常的流程走 · ==執行順序:== 按照注冊的順序倒序執行 ***
process_view
==執行時間:== 在process_request方法及路由匹配之后,視圖之前 · ==參數:== request:請求對象,與視圖中用到的request參數是同一個對象 view_func:將要執行的視圖函數(它是實際的函數對象,而不是函數的名稱作為字符串) view_args:url路徑中將傳遞給視圖的位置參數的元組 view_kwargs:url路徑中將傳遞給視圖的關鍵值參數的字典 · ==返回值:== None:按照正常的流程走 HttpResponse:它之后的中間件的process_view,及視圖不執行,執行所有中間件的process_response方法 · ==執行順序:== 按照注冊的順序執行 ***
process_exception
==此方法只在視圖中觸發異常時才被執行.==
==執行時間:== 視圖之后,process_response之前 · ==參數:== request:請求對象,與視圖中用到的request參數是同一個對象 exception:視圖函數異常產生的Exception對象 · ==返回值:== None:按照正常的流程走 HttpResponse對象:不再執行后面的process_exception方法 · ==執行順序:== 按照注冊的順序倒序執行 ***
process_template_response
==此方法必須在視圖函數返回的對象有一個render()方法(或者表明該對象是一個TemplateResponse對象或等價方法)時,才被執行.==
==執行時間:== 視圖之后,process_exception之前 · ==參數:== request:請求對象,與視圖中用到的request參數是同一個對象 response:是TemplateResponse對象(由視圖函數或者中間件產生) · ==返回值:== response:必須返回此對象,按照正常的流程走 · ==執行順序:== 按照注冊的順序倒序執行
中間件的執行流程
請求到達中間件之后,先按照正序執行每個注冊中間件的process_request方法,如果process_request方法返回的值是None,就依次執行;如果返回的值是HttpResponse對象,則不再執行后面的process_request方法,而是執行當前對象中間件的process_response方法,并將HttpResponse對象返回給瀏覽器。
也就是說,如果MIDDLEWARE注冊了6個中間件,執行過程中,第3個中間件返回了一個HttpResponse對象,那么第4, 5, 6中間件的process_request和process_response方法都不執行,而是順序執行3, 2, 1中間件的process_response方法。
process_request方法都執行完后,匹配路由,找到要執行的視圖函數,先不執行視圖函數,而是先執行中間件中的process_view方法,process_view方法返回None,則繼續按順序執行,所有的process_view方法執行完后,在執行視圖函數。
如果中間件 3 的process_view方法返回了一個HttpResponse對象,則4, 5, 6的process_view以及視圖函數都不執行了,而是直接從最后一個中間件,也就是中間件 6 的process_response方法開始倒序執行。
process_template_response 與 process_exception兩個方法的觸發是有條件的,執行順序也是倒序。總結所有的執行流程如下:
Django請求流程圖
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。