中間件
django的生命周期是: 前端請求 ---> nginx ---> uwsgi ---> 中間件 ---> url路由 ----> view試圖 --> orm ----> 拿到資料回傳給view ----> 試圖將資料渲染到模版中拿到字串 ---> 中間件- ---> uwsgi ---> nginx ----> 前端渲染,
當一個請求,首先從上往下運行這些類中process_request方法,之后進入django的從上往下執行每個類中的process_view方法,在然后就進入我們自定義的view.py檔案,如果你的試圖中有錯誤,那就會從下往上執行中間件中的process_exception方法,然后把錯誤資訊在通過process_response中回傳給客戶端,
一、簡介
- Django的中間件類似于Linux中的管道符;
- Django的中間件實質就是一個雷,類之中有Django已經定義好了一些方法;
- Django內部的中間件注冊在setting,py檔案;
- 對全域的http請求做處理的時候可以使用中間件;
- 中間件中的方法不一定要全部使用,需要哪個用哪個;
- Django的中間件繼承自MiddlewareMixin這個中間件
- MiddlewareMixin是呼叫了其內部的
__call__方法,__call__方法以反射的方式執行process_request和process_response方法,
二、中間件方法
-
process_request(self,request)
process_request有一個引數,就是request,這個request和視圖函式中的request是一樣的,
它的回傳值可以是None也可以是HttpResponse物件,回傳值是None的話,按正常流程繼續走,交給下一個中間件處理,如果是HttpResponse物件,Django將不執行視圖函式,而將相應物件回傳給瀏覽器,
在這個方法中是沒有return方法的,如果有那就會執行process_response方法,直接回傳給客戶端,一般情況下我們是不會在這里回傳內容的,除非你有需求,判斷發過來的請求過來的內容,如果不是很友好的請求,那么我們直接就可以在這回傳,直接卡死,讓這個請求直接都進不了我們的django中的內部程式
-
process_response(self, request, response)
它有兩個引數,一個是request,一個是response,request就是上述例子中一樣的物件,response是視圖函式回傳的HttpResponse物件,該方法的回傳值也必須是HttpResponse物件,
在這個方法中我們必須要有return方法,這樣才能一步一步的回傳給客戶端,當然你也可以寫一些東西在response里,在這里寫就是會在所有的response里都會有你所添加的內容!
-
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方法,再執行視圖函式
這個方法中是沒有return方法的,如果有那就走process_response方法,視圖函式不會執行 -
process_exception(self, request, exception)
該方法兩個引數:
一個HttpRequest物件
一個exception是視圖函式例外產生的Exception物件,這個方法只有在視圖函式中出現例外了才執行,它回傳的值可以是一個None也可以是一個HttpResponse物件,如果是HttpResponse物件,Django將呼叫模板和中間件中的process_response方法,并回傳給瀏覽器,否則將默認處理例外,如果回傳一個None,則交給下一個中間件的process_exception方法來處理例外,它的執行順序也是按照中間件注冊順序的倒序執行,
-
process_template_response(self,request,response)
它的引數,一個HttpRequest物件,response是TemplateResponse物件(由視圖函式或者中間件產生),
process_template_response是在視圖函式執行完成后立即執行,但是它有一個前提條件,那就是視圖函式回傳的物件有一個render()方法(或者表明該物件是一個TemplateResponse物件或等價方法),
三、中間件的應用
基于中間件實作簡單用戶登錄驗證
中間件版的登錄驗證需要依靠session,所以資料庫中要有django_session表,
定義路由
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'^index/$', views.index),
url(r'^login/$', views.login, name='login'),
]
視圖函式
from django.shortcuts import render, HttpResponse, redirect
def index(request):
return HttpResponse('this is index')
def home(request):
return HttpResponse('this is home')
def login(request):
if request.method == "POST":
user = request.POST.get("user")
pwd = request.POST.get("pwd")
if user == "Q1mi" and pwd == "123456":
# 設定session
request.session["user"] = user
# 獲取跳到登陸頁面之前的URL
next_url = request.GET.get("next")
# 如果有,就跳轉回登陸之前的URL
if next_url:
return redirect(next_url)
# 否則默認跳轉到index頁面
else:
return redirect("/index/")
return render(request, "login.html")
定義頁面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>
</head>
<body>
<form action="{% url 'login' %}">
<p>
<label for="user">用戶名:</label>
<input type="text" name="user" id="user">
</p>
<p>
<label for="pwd">密 碼:</label>
<input type="text" name="pwd" id="pwd">
</p>
<input type="submit" value="https://www.cnblogs.com/yanadoude/p/登錄">
</form>
</body>
</html>
定義中間件middlewares.py
class AuthMD(MiddlewareMixin):
white_list = ['/login/', ] # 白名單
balck_list = ['/black/', ] # 黑名單
def process_request(self, request):
from django.shortcuts import redirect, HttpResponse
next_url = request.path_info
print(request.path_info, request.get_full_path())
if next_url in self.white_list or request.session.get("user"):
return
elif next_url in self.balck_list:
return HttpResponse('This is an illegal URL')
else:
return redirect("/login/?next={}".format(next_url))
注冊
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',
'middlewares.AuthMD',
]
AuthMD中間件注冊后,所有的請求都要走AuthMD的process_request方法,
訪問的URL在白名單內或者session中有user用戶名,則不做阻攔走正常流程;
如果URL在黑名單中,則回傳This is an illegal URL的字串;
正常的URL但是需要登錄后訪問,讓瀏覽器跳轉到登錄頁面,
注:AuthMD中間件中需要session,所以AuthMD注冊的位置要在session中間的下方,
四、附:Django請求流程圖

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/137151.html
標籤:Python
上一篇:YAML語法
下一篇:08.Django-信號
