在cookie和session的應用中,經過在視圖函數內添加裝飾器判斷用戶是否登陸,把沒有登陸的用戶請求跳轉到登陸頁面,經過給幾個特定視圖函數加裝飾器實現了這個需求。可是之後添加的視圖函數可能也須要加上裝飾器,這樣是否是稍微有點繁瑣數據庫
在此,經過中間件可經過簡單適宜的方式實現認證等操做django
1.什麼是中間件瀏覽器
中間件是一個用來處理Django的請求和響應的框架級別的鉤子,是一個輕量、低級別的插件系統,用於在全局範圍內改變Django的輸入和輸出。每一箇中間件組件都負責作一些特定的功能。安全
可是因爲其影響的是全局,因此須要謹慎使用,使用不當會影響性能cookie
簡單的說,中間件是幫助咱們在視圖函數執行以前和執行以後均可以作一些額外的操做,它本質上就是一個自定義類,在類中定義方法,Django框架會在請求的特定的時間去執行相應的方法session
Django自己在setting.py中自定義了一些中間件,MIDDLEWARE配置項是一個列表,列表中存放字符串,這些字符串其實就是類,也就是中間件:框架
MIDDLEWARE = [
# 安全相關
'django.middleware.security.SecurityMiddleware',
# session相關,Django每次接收到request請求的時候會
# 給request添加session方法,因此在視圖內可經過原點的方式調用session
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# csrf 校驗
'django.middleware.csrf.CsrfViewMiddleware',
# 認證相關
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
2.自定義中間件函數
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)
可自定義以上五種中間件,一般使用的也就process_request和process_response,這些方法的返回值能夠是一個None或一個HttpResponse對象,若是是None,則繼續按照django定義的規則向後繼續執行,若是是HttpResponse對象,則直接將該對象返回給用戶性能
附:Django處理請求、響應的過程url
示例:
class Exemple(MiddlewareMixin): def process_request(self, request): print("Exemple中process_request方法") def process_view(self, request, view_func, view_args, view_kwargs): print("Exemple中process_view方法") print(view_func.__name__) # return HttpResponse("Excemple中的process_view方法") # def process_response(self, request, response): # print("Exemple中的process_response方法") # return response
1)prosess_request
process_request有一個參數,就是request,這個request和視圖函數中的request是同樣的,返回值能夠是None也能夠是HttpResponse對象
返回值是None的話,按正常流程繼續走,交給下一個中間件處理,若是是HttpResponse對象,Django將不執行視圖函數,而將相應對象返回給瀏覽器
多箇中間件中的process_response方法是按照MIDDLEWARE中的註冊順序倒序執行的,也就是說第一個中間件的process_request方法首先執行,而它的process_response方法最後執行,最後一箇中間件的process_request方法最後一個執行,它的process_response方法是最早執行
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse, redirect, render class Login(MiddlewareMixin): def process_request(self, request): print("Login中process_request方法") class Exemple(MiddlewareMixin): def process_request(self, request): print("Exemple中process_request方法")
在settings.py的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', # 註冊自定義中間件 'middlewares.login_middlewares.Login', 'middlewares.login_middlewares.Exemple', ]
2)process_response
有兩個參數,一個是request,一個是response,request就是上述例子中同樣的對象,response是視圖函數返回的HttpResponse對象,該方法的返回值也必須是HttpResponse對象
多箇中間件中的process_response方法是按照MIDDLEWARE中的註冊順序倒序執行的,也就是說第一個中間件的process_request方法首先執行,而它的process_response方法最後執行,最後一箇中間件的process_request方法最後一個執行,它的process_response方法是最早執行
3)process_view
process_view(self, request, view_func, view_args, view_kwargs)該方法有四個參數
request HttpRequest對象
view_func Django即將使用的視圖函數(它是實際的函數對象,而不是函數的名稱做爲字符串)
view_args 將傳遞給視圖的位置參數的列表
view_kwargs 將傳遞給視圖的關鍵字參數的字典。 view_args和view_kwargs都不包含第一個視圖參數(request)
Django會在調用視圖函數以前調用process_view方法,它應該返回None或一個HttpResponse對象:
若是返回None,Django將繼續處理這個請求,執行任何其餘中間件的process_view方法,而後在執行相應的視圖
若是它返回一個HttpResponse對象,Django不會調用適當的視圖函數,它將執行中間件的process_response方法並將應用到該HttpResponse並返回結果
process_view方法是在process_request以後,視圖函數以前執行的,執行順序按照MIDDLEWARE中的註冊順序從前到後順序執行的
4)process_exception
process_exception(self, request, exception)該方法有兩個參數
request HttpRequest對象
exception 視圖函數異常產生的Exception對象
只有在視圖函數中出現異常了才執行,它返回的值能夠是一個None也能夠是一個HttpResponse對象:
若是是HttpResponse對象,Django將調用模板和中間件中的process_response方法,並返回給瀏覽器,不然將默認處理異常
若是返回一個None,則交給下一個中間件的process_exception方法來處理異常。它的執行順序也是按照中間件註冊順序的倒序執行
5)process_template_response
process_template_response(self, request, response)該方法有兩個參數
request HttpRequest對象
exception TemplateResponse對象,由視圖函數或者中間件產生
視圖函數執行完成後當即執行,可是它有一個前提條件,那就是視圖函數返回的對象有一個render()方法,順序是倒序(或者代表該對象是一個TemplateResponse對象或等價方法)
3.中間件的執行過程
請求到達中間件以後,先按照正序執行每一個註冊中間件的process_reques方法,process_request方法返回的值是None,就依次執行,若是返回的值是HttpResponse對象,再也不執行後面的process_request方法,而是執行當前對應中間件的process_response方法,將HttpResponse對象返回給瀏覽器
舉例說明:若是MIDDLEWARE中註冊了6箇中間件,執行過程當中,第3箇中間件返回了一個HttpResponse對象,那麼後面的第四、五、6的中間件的process_request和process_response方法都不執行,倒序執行第3-第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中基於中間件的認證登陸
1)Django目錄下建立存放自定義中間件的包,建立中間件的py文件
注意:自定義的中間件必須繼承MiddlewareMixin
中間件登陸認證時須要依靠session,因此數據庫中須要建立好django_session表
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import redirect class Login(MiddlewareMixin): def process_request(self, request): url = request.path_info if not request.path_info.startswith("/login/"): login_flag = request.session.get("login") if not login_flag: rep = redirect("/login/?next={}".format(url)) return rep
2)在setting.py中註冊中間件
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', # 註冊自定義的中間件 'middlewares.login_middlewares.Login', ]
總結:
# 每一箇中間件都有五種可重寫的方法 process_request(self,request) 1.在urls.py以前執行 2.按照列表中的註冊順序執行 3.返回值:返回None不作任何處理繼續後面的 返回響應對象,直接跳出,後面的中間件、urls.py都再也不執行 process_view(self, request, view_func, view_args, view_kwargs) 1.在urls.py以後以及views.py以前執行 2.按照列表中的註冊順序執行 3.返回值:返回None放行 返回響應對象,就直接跳出,倒序依次執行全部中間件的process_response方法 process_response(self, request, response) 1.在views.py以後執行 2.按照列表中的註冊倒序執行 3.返回值:必須有返回值,返回的是相應對象 process_template_response(self,request,response) process_exception(self, request, exception)