中間件的概念
中間件顧名思義,是介於request與response處理之間的一道處理過程,相對比較輕量級,而且在全局django
上改變django的輸入與輸出。由於改變的是全局,因此須要謹慎實用,用很差會影響到性能。瀏覽器
Django的中間件的定義:session
Middleware
is` `a framework of hooks into Django’s request
/response processing.
app
It’s a light, low
-level 「plugin」 system
forglobally altering Django’sinput
or
框架
output
.ide
中間件是一個用來處理Django的請求和響應的框架級別的鉤子。它是一個輕量、低級別的插件系統,用於在全局範圍內改變Django的輸入和輸出。每一箇中間件組件都負責作一些特定的功能。函數
鉤子:在某個位置預留了位置,沒有掛鉤子函數的話繼續執行,若是寫了鉤子函數就執行完後繼續執行。post
應用:性能
若是想修改請求,例如被傳送到view中的HttpRequest對象。 或者想修改view返回的HttpResponse對象,這些均可以經過中間件來實現。ui
可能還想在view執行以前作一些操做,這種狀況就能夠用 middleware來實現。
咱們可能頻繁在view使用
request.user
吧。 Django想在每一個view執行以前把user設置request的屬性,因而就用了一箇中間件來實現這個目標。因此Django提供了能夠修改request 對象的中間
件
AuthenticationMiddleware
。- 中間件能夠用來幹什麼?
- 用戶登陸
日誌記錄
crsf:對全部的post請求作了一個驗證
session
權限管理- 注意:
對於全部請求的批量作處理的時候用中間件
單獨對某幾個函數作處理的時候用裝飾器Django默認的Middleware:
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',
]每個中間件都有具體的功能
- 使用步驟
中間件使用步驟步驟: 1、、先建一個文件夾,裏面寫一個py文件 2、、而後開始寫類 1.中間件就是一個類,類裏面寫幾個方法 class M1(MiddlewareMixin): 必須繼承 def process_request(self,request): request:請求裏面的全部的東西 print("m1.request_request") 這個方法裏面別輕易返回值,要是有返回值就再也不繼續執行後面的了,執行本身的process_response和上邊的response 通常是無返回值的:繼續執行後續的中間件和視圖函數 def process_response(self,request,response): return response 2.在settings中的MIDDLEWARE加上路徑 文件夾名稱.py文件名稱.類名 3.找到繼承的那個類,吧那個類拿過來 通常不要用導入的方法,否則有時候更新了就沒有這個類了,你就把它繼承的那個類拿過來,
自定義中間件
中間件能夠定義五個方法,分別是:(主要的是process_request和process_response)
- process_request(self,request)
- process_view(self, request, view_func, view_args, view_kwargs)
- process_template_response(self,request,response)
- process_exception(self, request, exception)
- process_response(self, request, response)
以上方法的返回值能夠是None或一個HttpResponse對象,
若是是None,則繼續按照django定義的規則向後繼續執行,
若是是HttpResponse對象,則直接將該對象返回給用戶。
- 總結:
五個方法總結五個方法 - 參數,執行時間,執行順序 - 1、process_request(self, request) - 執行時間:在視圖函數執行以前 - 參數: - request:視圖函數用到中用到的request - 執行順序:按照註冊順序執行 - 返回值: - None:正常流程 - HttpResponse對象:當前中間件後面的中間件的process_request方法 process_Response方法和視圖的Http_Response對象不執行,執行當前 中間件的process_Response方法以及以前的process_reques方法 - 2、process_response(self, request, response) - 執行時間:在視圖函數執行以後 - 參數: - request:視圖函數用到中用到的request - response:視圖函數中返回的response對象,若是中間件返回response對象,就不走 視圖函數了 - 執行順序:按照註冊順序倒序執行 - 返回值: - 不能爲None,不然會報錯 - 必須是response對象 - 3、process_view(self, request, view_func, view_args, view_kwargs) - 執行時間:在視圖函數以前,在process_reques方法以後,以及路由匹配以後 - 參數: - request:視圖函數用到中用到的request - view_func:要執行的視圖函數 - view_args:視圖函數的位置參數 - view_kwargs:視圖函數的關鍵字參數 - 返回值: - None:正常流程 - HttpResponse對象: - 執行屬性:按照註冊順序執行 - 4、process_exception(self, request, exception) - 執行時間: - 觸發條件:有異常才執行 - 在視圖函數以後,在process_response以前 - 參數: - request:視圖函數用到中用到的request - exception:錯誤信息對象 - 返回值:HttpResponse對象: - None:正常執行 - HttpResponse對象: - 註冊順序以前的全部中間件的process_exception方法不走了 - 執行全部中間件的的process_response - 執行順序:按照註冊順序倒序執行 - 5、process_template_response(self, request, response) - 執行時間: - 觸發條件:返回的response對象要有一個render方法 - 在視圖函數以後,在process_response方法以前 - 參數「 - request:視圖函數用到中用到的request - response:視圖函數中返回的response對象 - 返回值: - 不能爲None,不然會報錯 - 必須是response對象 - 執行順序:按照註冊順序倒序執行(不會截斷,可以重寫)- process_request(self,request) 1、中間件的process_request方法是在執行視圖函數以前執行的。 2、當配置多箇中間件時,會按照MIDDLEWARE中的註冊順序,也就是列表的索引值,從前到後依次執行的。 3、不一樣中間件之間傳遞的request都是同一個對象 - process_response(self, request, response) 1、process_response方法是在視圖函數以後執行的,而且順序是MD1比MD2先執行。(此時settings.py中 MD2比MD1先註冊) 2、多箇中間件中的process_response方法是按照MIDDLEWARE中的註冊順序倒序執行的,也就是說第一個中間件的process_request方法首先執行,而它的process_response方法最後執行,最後一箇中間件的process_request方法最後一個執行,它的process_response方法是最早執行。 - process_view(self, request, view_func, view_args, view_kwargs) 1、Django會在調用視圖函數以前調用process_view方法。 2、它應該返回None或一個HttpResponse對象。 若是返回None,Django將繼續處理這個請求,執行任何其餘中間件的process_view方法,而後在執行相應的視圖。 若是它返回一個HttpResponse對象,Django不會調用適當的視圖函數。 它將執行中間件的process_response方法並將應用到該HttpResponse並返回結果。 3、process_view方法是在process_request以後,視圖函數以前執行的,執行順序按照MIDDLEWARE中的註冊順序從前到後順序執行的。 - process_exception(self, request, exception) 1、這個方法只有在視圖函數中出現異常了才執行,它返回的值能夠是一個None也能夠是一個HttpResponse對象。若是是HttpResponse對象,Django將調用模板和中間件中的process_response方法,並返回給瀏覽器,不然將默認處理異常。若是返回一個None,則交給下一個中間件的process_exception方法來處理異常。它的執行順序也是按照中間件註冊順序的倒序執行。 - process_template_response(self,request,response) 1、process_template_response是在視圖函數執行完成後當即執行,可是它有一個前提條件,那就是視圖函數返回的對象有一個render()方法(或者代表該對象是一個TemplateResponse對象或等價方法)。 二、視圖函數執行完以後,當即執行了中間件的process_template_response方法,順序是倒序,先執行MD1的,在執行MD2的,接着執行了視圖函數返回的HttpResponse對象的render方法,返回了一個新的HttpResponse對象,接着執行中間件的process_response方法。
process_request,process_response
當用戶發起請求的時候會依次通過全部的的中間件,這個時候的請求時process_request,最後到達views的函數中,views函數處理後,在依次穿過中間件,這個時候是process_response,最後返回給請求者。
咱們也能夠本身定義一箇中間件,咱們能夠本身寫一個類,可是必須繼承MiddlewareMixin
須要導入
from django.utils.deprecation import MiddlewareMixin
in views:
def index(request):
print("view函數...")
return HttpResponse("OK")in Mymiddlewares.py:
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
class Md1(MiddlewareMixin):
def process_request(self,request):
print("Md1請求")
def process_response(self,request,response):
print("Md1返回")
return response
class Md2(MiddlewareMixin):
def process_request(self,request):
print("Md2請求")
#return HttpResponse("Md2中斷")
def process_response(self,request,response):
print("Md2返回")
return response結果:
Md1請求
Md2請求
view函數...
Md2返回
Md1返回注意:若是當請求到達請求2的時候直接不符合條件返回,即return HttpResponse("Md2中斷"),程序將把請求直接發給中間件2返回,而後依次返回到請求者,結果以下:
返回Md2中斷的頁面,後臺打印以下:
Md1請求
Md2請求
Md2返回
Md1返回流程圖以下:
process_view
process_view(self, request, callback, callback_args, callback_kwargs)
Mymiddlewares.py修改以下
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
class Md1(MiddlewareMixin):
def process_request(self,request):
print("Md1請求")
#return HttpResponse("Md1中斷")
def process_response(self,request,response):
print("Md1返回")
return response
def process_view(self, request, callback, callback_args, callback_kwargs):
print("Md1view")
class Md2(MiddlewareMixin):
def process_request(self,request):
print("Md2請求")
return HttpResponse("Md2中斷")
def process_response(self,request,response):
print("Md2返回")
return response
def process_view(self, request, callback, callback_args, callback_kwargs):
print("Md2view")結果以下:
Md1請求
Md2請求
Md1view
Md2view
view函數...
Md2返回
Md1返回下圖進行分析上面的過程:
當最後一箇中間的process_request到達路由關係映射以後,返回到中間件1的process_view,而後
依次往下,到達views函數,最後經過process_response依次返回到達用戶。
process_view能夠用來調用視圖函數:
class Md1(MiddlewareMixin):
def process_request(self,request):
print("Md1請求")
#return HttpResponse("Md1中斷")
def process_response(self,request,response):
print("Md1返回")
return response
def process_view(self, request, callback, callback_args, callback_kwargs):
# return HttpResponse("hello")
response=callback(request,*callback_args,**callback_kwargs)
return response結果以下:
Md1請求
Md2請求
view函數...
Md2返回
Md1返回注意:process_view若是有返回值,會越過其餘的process_view以及視圖函數,可是全部的
process_response都還會執行。
process_exception
process_exception(self, request, exception)
示例修改以下:
class Md1(MiddlewareMixin):
def process_request(self,request):
print("Md1請求")
#return HttpResponse("Md1中斷")
def process_response(self,request,response):
print("Md1返回")
return response
def process_view(self, request, callback, callback_args, callback_kwargs):
# return HttpResponse("hello")
# response=callback(request,*callback_args,**callback_kwargs)
# return response
print("md1 process_view...")
def process_exception(self):
print("md1 process_exception...")
class Md2(MiddlewareMixin):
def process_request(self,request):
print("Md2請求")
# return HttpResponse("Md2中斷")
def process_response(self,request,response):
print("Md2返回")
return response
def process_view(self, request, callback, callback_args, callback_kwargs):
print("md2 process_view...")
def process_exception(self):
print("md1 process_exception...")結果以下:
Md1請求
Md2請求
md1 process_view...
md2 process_view...
view函數...
Md2返回
Md1返回流程圖以下:
當views出現錯誤時:
將md2的process_exception修改以下:
def process_exception(self,request,exception):
print("md2 process_exception...")
return HttpResponse("error")結果以下:
Md1請求
Md2請求
md1 process_view...
md2 process_view...
view函數...
md2 process_exception...
Md2返回
Md1返回process_template_response(用的比較少)
process_template_response(self, request, response)
它的參數,一個HttpRequest對象,response是TemplateResponse對象(由視圖函數或者中間件產生)。
process_template_response是在視圖函數執行完成後當即執行,可是它有一個前提條件,那就是視圖函數返回的對象有一個render()方法(或者代表該對象是一個TemplateResponse對象或等價方法)。
class MD1(MiddlewareMixin): def process_request(self, request): print("MD1裏面的 process_request") def process_response(self, request, response): print("MD1裏面的 process_response") return response def process_view(self, request, view_func, view_args, view_kwargs): print("-" * 80) print("MD1 中的process_view") print(view_func, view_func.__name__) def process_exception(self, request, exception): print(exception) print("MD1 中的process_exception") return HttpResponse(str(exception)) def process_template_response(self, request, response): print("MD1 中的process_template_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 def process_view(self, request, view_func, view_args, view_kwargs): print("-" * 80) print("MD2 中的process_view") print(view_func, view_func.__name__) def process_exception(self, request, exception): print(exception) print("MD2 中的process_exception") def process_template_response(self, request, response): print("MD2 中的process_template_response") return responseviews.py中:
def index(request): print("app01 中的 index視圖") def render(): print("in index/render") return HttpResponse("O98K") rep = HttpResponse("OK") rep.render = render return rep訪問index視圖,終端輸出的結果:
MD2裏面的 process_request MD1裏面的 process_request -------------------------------------------------------------------------------- MD2 中的process_view <function index at 0x000001C111B97488> index -------------------------------------------------------------------------------- MD1 中的process_view <function index at 0x000001C111B97488> index app01 中的 index視圖 MD1 中的process_template_response MD2 中的process_template_response in index/render MD1裏面的 process_response MD2裏面的 process_response從結果看出:
視圖函數執行完以後,當即執行了中間件的process_template_response方法,順序是倒序,先執行MD1的,在執行MD2的,接着執行了視圖函數返回的HttpResponse對象的render方法,返回了一個新的HttpResponse對象,接着執行中間件的process_response方法。