中間件
一.什麼是中間件
中間件是一個用來處理Django的請求和響應的框架級別的鉤子。它是一個輕量、低級別的插件系統,用於在全局範圍內改變Django
的輸入和輸出。每一箇中間件組件都負責作一些特定的功能,中間件是幫助咱們在視圖函數執行以前和執行以後均可以作一些額外的
操做,它本質上就是一個自定義類,類中定義了幾個方法,Django框架會在處理請求的特定的時間去執行這些方法。
二.自定義中間件
(一)中間件能夠定義五個方法,分別是:(主要的是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.導入 from django.utils.deprecation import MiddlewareMixin
2.在settings.py的MIDDLEWARE配置項中註冊上述兩個自定義中間件:
'app01.my_middlewares.MD2',
'app01.my_middlewares.MD1'
三.方法:
1.process_request
執行時間:視圖函數以前
參數:request (同視圖函數參數)
執行順序:按註冊的順序
返回值:若是是none: 則繼續按規則執行
若是是 Httpresponse對象: 跳事後面中間件的request方法,直接執行相對應的中間件的response方法.
示例:
class MD1(MiddlewareMixin):
def process_request(self,request): #正序
print("這是MD1request方法")
2.process_response
執行時間:視圖函數後
參數:request response
執行順序:按倒序執行
返回值:必須return response
若是返回Httpresponse對象,返回當前Httpresponse對象則直接從最後一箇中間件的response開始執行
示例
class MD1(MiddlewareMixin):
def process_response(self,request,response): #倒序
print('這是MD1response方法')
return response
3.process_view
執行時間:request以後,視圖函數以前
參數:self, request, view_func, view_args, view_kwargs
執行順序:按註冊順序執行
返回值:若是是none,正常執行
若是是Httpresponse對象,不執行後面的中間件的view方法,,直接從最後一箇中間件的response方法開始執行(執行所有)
示例:
class MD1(MiddlewareMixin):
def process_view(self,request,view_func,view_args,view_kwargs): #順序
# view_func(request)
print('這是MD1view 方法')
# return HttpResponse('ok') #不執行MD2的view方法從最後一箇中間件的response開始執行倒序
4.process_exception 報錯纔會觸發
執行時間: 視圖函數以後,response以前
參數: self, request, exception
執行順序:倒序執行
返回值:返回none:不對錯誤進行處理,交給下一個中間件進行處理
返回Httpresponse對象:不執行後面的中間件的該方法,直接執行全部中間件的response方法
示例:
class MD1(MiddlewareMixin):
def process_exception(self,request,exception): #報錯才顯示 視圖以後 倒序
print('這是MD1exception 方法')
# return HttpResponse('你出錯了') 不執行其以後中間件的exception方法 ,直接從最後一箇中間件的response方法開始執行
5.process_template_response(用的比較少) 視圖函數返回的對象中有render方法才觸發該方法
執行時間:視圖函數以後,response以前
參數:(self, request, response)
執行順序:倒序
返回值:必須有return
視圖函數執行完以後,當即執行了中間件的process_template_response方法,順序是倒序,先執行MD1的,在執行MD2的,
接着執行了視圖函數返回的HttpResponse對象的render方法,返回了一個新的HttpResponse對象,接着執行中間件的
process_response方法 (倒序)。
做業:
中間件實現登錄驗證
中間件(my_middleware.py):
from django.middleware.security import SecurityMiddleware
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render, HttpResponse,redirect
class AuthMD(MiddlewareMixin):
white_list=['/home/',"/login/"] #白名單 定義一個字段白名單(靜態屬性)
black_list=[''] #黑名單 #定義一個黑名單
def process_request(self,request): #全部請求都必須通過process_request
next_url=request.path_info #獲取用戶發送請求中的路徑
print(next_url) #login
if next_url in self.black_list: #判斷 用戶請求路徑是否在黑名單中
return HttpResponse('This is an illegal URL') #若是在則響應''
elif next_url in self.white_list or request.session.get('user'): #若是路徑在白名單中則能夠執行(匹配url,視圖函數)
return
else:
return redirect('/login/?next={}'.format(next_url)) # 若是是其餘則跳轉到login頁面 後面拼接上用戶的路徑,
#匹配路徑與函數
url.py:
urlpatterns = [ url(r'^admin/', admin.site.urls), # url(r"^work/",views.work), url(r"^login/$",views.login), url(r'^index/$',views.index), url(r'^home/$',views.home), ]
views.py:
from django.shortcuts import render,redirect,HttpResponse def index(request): #登錄後才能訪問 return HttpResponse('這是index') def home(request): #隨意訪問 return HttpResponse('這是home') def login(request): #隨意訪問 if request.method=='POST': user=request.POST.get("user") #獲取用戶名 pwd=request.POST.get('pwd') #獲取密碼 if user=="alex" and pwd=='alex': #若是驗證成功 request.session['user']=user #設置session next_url=request.GET.get('next')#獲取路徑後面拼接的查找內容 if next_url:#若是路徑存在 return redirect(next_url) #跳轉到該頁面 else: #若是不存在默認跳轉到index頁面 return redirect('/index/') return render(request,'login.html') #若是是get請求返回login頁面
login.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Title</title> </head> <body> <form action="" method="post"> {% csrf_token %} <p> <lable for="user">用戶名:</lable> <input type="text" name="user" id="user"> </p> <p> <lable for="pwd">密碼:</lable> <input type="password" name="pwd" id="pwd"> </p> <input type="submit" value="登錄"> </form> </body> </html>
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', 'app01.my_middlewares.AuthMD', ]