Django基礎(chǔ)CBV裝飾器和中間件的應(yīng)用示例
1. CBV加裝飾器
CBV
加裝飾器有三種方法,
案例:要求登錄(不管get請求還是post請求)后才可以訪問
HTML代碼
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div> <p>Hello Index</p> </div> </body> </html>
login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div> <form action="" method="post"> <p>username:<input type="text" name="username"></p> <p>password:<input type="password" name="password"></p> <p><input type="submit" value="提交"></p> </form> </div> </body> </html>
views.py
# CBV加裝飾器方法一: from django.shortcuts import render, HttpResponse, redirect from django.views import View from django.utils.decorators import method_decorator # django提交加裝飾器方法 # Create your views here. # 裝飾器 def login_auth(func): def inner(request, *args, **kwargs): if request.session.get("is_login"): res = func(*args, **kwargs) return res else: return redirect('/login/') return inner class Index(View): # 方法一在每個需要驗證的地方都加上裝飾器 @method_decorator(login_auth) def get(self, request): print("get 請求") return render(request, "index.html") # 個需要驗證的地方加上裝飾器 @method_decorator(login_auth) def post(self, request): print("post 請求") return HttpResponse("post") def login(request): if request.method == "POST": name = request.POST.get("username") password = request.POST.get("password") if name == "hans" and password == "123": request.session['is_login'] = True print("登錄成功") return render(request, "login.html") # CBV加裝飾器方法二: from django.shortcuts import render, HttpResponse, redirect from django.views import View from django.utils.decorators import method_decorator # Create your views here. # 裝飾器 def login_auth(func): def inner(request, *args, **kwargs): if request.session.get("is_login"): res = func(*args, **kwargs) return res else: return redirect('/login/') return inner # 方法二 在類的上面加上,name為具體要加的函數(shù) @method_decorator(login_auth, name='post') @method_decorator(login_auth, name='get') class Index(View): def get(self, request): print("get 請求") return render(request, "index.html") def post(self, request): print("post 請求") return HttpResponse("post") def login(request): if request.method == "POST": name = request.POST.get("username") password = request.POST.get("password") if name == "hans" and password == "123": request.session['is_login'] = True print("登錄成功") return render(request, "login.html") # CBV加裝飾器方法三: from django.shortcuts import render, HttpResponse, redirect from django.views import View from django.utils.decorators import method_decorator # Create your views here. # 裝飾器 def login_auth(func): def inner(request, *args, **kwargs): if request.session.get("is_login"): res = func(*args, **kwargs) return res else: return redirect('/login/') return inner class Index(View): #方法三 使用dispatch給所有的方法添加裝飾器 @method_decorator(login_auth) def dispatch(self, request, *args, **kwargs): return super().dispatch(request, *args, **kwargs) def get(self, request): print("get 請求") return render(request, "index.html") def post(self, request): print("post 請求") return HttpResponse("post") def login(request): if request.method == "POST": name = request.POST.get("username") password = request.POST.get("password") if name == "hans" and password == "123": request.session['is_login'] = True print("登錄成功") return render(request, "login.html")
urls.py
from django.contrib import admin from django.urls import path from wrapperMidd import views urlpatterns = [ path('admin/', admin.site.urls), path('index/', views.Index.as_view()), path('login/', views.login), ]
訪問地址:http://127.0.0.1:8000/index
get
的請求使用POSTMAN
工具
2. Django中間件
2.1 Django中間件介紹
中間件是 Django
請求/響應(yīng)處理的鉤子框架。它是一個輕量級的、低級的“插件”系統(tǒng),用于全局改變 Django
的輸入或輸出。
每個中間件組件負責(zé)做一些特定的功能,Django
中自帶了七個中間件
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', # 安全中間件,為請求/響應(yīng)周期提供了若干安全增強功能。每一項都可以通過設(shè)置獨立地啟用或禁用。 'django.contrib.sessions.middleware.SessionMiddleware', # 啟用會話支持 'django.middleware.common.CommonMiddleware', # “通用”中間件 'django.middleware.csrf.CsrfViewMiddleware', # CSRF 保護中間件,通過在 POST 表單中添加隱藏的表單字段,并檢查請求的正確值,增加對跨站點偽造請求的保護。 'django.contrib.auth.middleware.AuthenticationMiddleware', # 驗證中間件,將代表當(dāng)前登錄的用戶的 user 屬性添加到每個傳入的 HttpRequest 對象中 'django.contrib.messages.middleware.MessageMiddleware', # 消息中間件,啟用基于 cookie 和會話的消息支持 'django.middleware.clickjacking.XFrameOptionsMiddleware', # X-Frame-Options 中間件,簡單的 通過 X-Frame-Options 頭的點擊劫持保護。 ]
中間件(Middleware
)在整個Django
的request/response
處理機制中的角色如下所示:
HttpRequest -> Middleware(request) -> View -> Middleware(response) -> HttpResponse
中間件常用于權(quán)限校驗、限制用戶請求、打印日志、改變輸出內(nèi)容等多種應(yīng)用場景.而且中間件對Django的輸入或輸出的改變是全局的。
Django
中間件作用:
- 修改請求,即傳送到 view 中的 HttpRequest 對象。
- 修改響應(yīng),即 view 返回的 HttpResponse 對象。
中間件執(zhí)行順序:
2.2 自定義中間件
中間件可以定義四個方法:
process_request(self,request)
process_view(self, request, view_func, view_args, view_kwargs)
process_exception(self, request, exception)
process_response(self, request, response)
主要為process_request
和process_response
在應(yīng)用目錄下新建一個 py 文件,名字自定義。
在應(yīng)用目錄下創(chuàng)建myMiddle.py myMiddle.py: from django.utils.deprecation import MiddlewareMixin class myMinddle(MiddlewareMixin): def process_request(self, request): # 在視圖之前執(zhí)行 print("這是自定義中間件 請求1") def process_response(self,request, response): #在視圖之后執(zhí)行 print("這是自定義中間件 響應(yīng)1") return response
把自定義的中間件注冊到setting.py
的 MIDDLEWARE
里面:
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', 'wrapperMidd.myMinddle.myMinddle', # 自定義中間件 ]
測試:
views.py: from django.shortcuts import render, HttpResponse, redirect def testMinddle(request): print("testMinddle") return HttpResponse("TEST") urls.py: from django.contrib import admin from django.urls import path from appName import views urlpatterns = [ path('admin/', admin.site.urls), path('testMinddle/', views.testMinddle), ] # 訪問:http://127.0.0.1:8000/testMinddle/ # 結(jié)果: """ 這是自定義中間件 請求1 testMinddle 這是自定義中間件 響應(yīng)1 """
增加兩個自定義中間件,執(zhí)行過程:
myMiddle.py: from django.utils.deprecation import MiddlewareMixin class myMinddle(MiddlewareMixin): def process_request(self, request): print("這是自定義中間件 請求1") def process_response(self,request, response): print("這是自定義中間件 響應(yīng)1") return response class myMinddle2(MiddlewareMixin): def process_request(self, request): print("這是自定義中間件 請求2") def process_response(self,request, response): print("這是自定義中間件 響應(yīng)2") return response setting.py: MIDDLEWARE = [ ...... 'wrapperMidd.myMinddle.myMinddle', 'wrapperMidd.myMinddle.myMinddle2', ] # 訪問:http://127.0.0.1:8000/testMinddle/ # 結(jié)果 """ 這是自定義中間件 請求1 這是自定義中間件 請求2 testMinddle 這是自定義中間件 響應(yīng)2 這是自定義中間件 響應(yīng)1 """
如果在第一個中間件直接返回,執(zhí)行順序如果:
myMiddle.py: from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse class myMinddle(MiddlewareMixin): def process_request(self, request): print("這是自定義中間件 請求1") return HttpResponse("request") """在這里直接返回""" def process_response(self,request, response): print("這是自定義中間件 響應(yīng)1") return response class myMinddle2(MiddlewareMixin): def process_request(self, request): print("這是自定義中間件 請求2") def process_response(self,request, response): print("這是自定義中間件 響應(yīng)2") return response # 訪問:http://127.0.0.1:8000/testMinddle/ # 結(jié)果: 網(wǎng)頁上顯示:request 后臺顯示: """ 這是自定義中間件 請求1 這是自定義中間件 響應(yīng)1 """
2.3 自定義中間件總結(jié)
自定義中間件先執(zhí)行process_request
再執(zhí)行views.py
里的視圖函數(shù),最后再執(zhí)行process_response
,而且process_response
函數(shù)必須要返回 return response
如果有多個自定義中間件,則執(zhí)行順序按settings.py
里自上而下執(zhí)行,寫在上面的先執(zhí)行。執(zhí)行順序
自定義中間件1 process_request--->自定義中間件2 process_request-->視圖函數(shù)-->自定義中間件2 process_response -->自定義中間件1 process_response
如果自定義中間件的process_request
里有return
返回,而這個中間件還是在上面,則它會執(zhí)行自己定義的process_request
和process_response
,則視圖函數(shù)和其他的中間件都不執(zhí)行
如果自定義中間件的process_request
里有return
返回,而這個中間件上面還有其他的中間件,則會自上而下執(zhí)行,執(zhí)行到自定義中間件的process_request
后就會執(zhí)行process_response
,則視圖函數(shù)和它下面的中間件都不執(zhí)行
MIDDLEWARE = [ ...其他中間件... '自定義中間件1', '自定義中間件2', # 自定義中間件2里使用return直接返回 '自定義中間件3', ] 執(zhí)行順序: """ 其他中間件 process_request --> 自定義中間件1 process_request --> 自定義中間件2 process_request --> 自定義中間件2 process_response --> 自定義中間件1 process_response -->其他中間件 process_response """ 視圖函數(shù)和自定義中間件3是不執(zhí)行的
2.4 其他中間件函數(shù)
process_view
process_view在process_request之后,路由轉(zhuǎn)發(fā)到視圖,執(zhí)行視圖之前執(zhí)行。
process_view() 只在 Django 調(diào)用視圖前被調(diào)用。它應(yīng)該返回 None 或 HttpResponse 對象。如果它返回 None ,Django 將繼續(xù)處理這個請求,執(zhí)行任何其他的 process_view() ,然后執(zhí)行相應(yīng)的視圖。如果它返回 HttpResponse 對象,Django 不會去影響調(diào)用相應(yīng)的視圖;它會將響應(yīng)中間件應(yīng)用到 HttpResponse 并返回結(jié)果。
函數(shù)定義:
process_view(request, view_func, view_args, view_kwargs)
request 是一個 HttpRequest 對象。
view_func 是一個 Django 將要使用的 Python 函數(shù)。(這是一個真實的函數(shù)對象,不是函數(shù)的名稱);view_args 是一個用來傳遞給視圖的位置參數(shù)列表,;
view_kwargs 是一個用來傳遞給視圖的關(guān)鍵字參數(shù)字典。
view_args 和 view_kwargs 都不包含第一個視圖參數(shù) ( request )。
process_exception
視圖執(zhí)行中發(fā)生異常時執(zhí)行。
當(dāng)視圖引發(fā)異常時,Django 會調(diào)用 process_exception()。process_exception() 應(yīng)該返回 None 或 HttpResponse 對象。如果它返回一個 HttpResponse 對象,模板響應(yīng)和響應(yīng)中間件將被應(yīng)用且會將結(jié)果響應(yīng)返回瀏覽器。否則,就會開始默認異常處理( default exception handling )。
再次,中間件在響應(yīng)階段會按照相反的順序運行,其中包括 process_exception 。如果異常中間件返回一個響應(yīng),那么中間件之上的中間件類的 process_exception 方法根本不會被調(diào)用。
函數(shù)定義:
process_exception(request, exception)
request 是一個 HttpRequest 對象。 exception 是一個由視圖函數(shù)引發(fā)的 Exception 對象。
process_template_response
視圖函數(shù)剛執(zhí)行完畢,process_response之前執(zhí)行。
process_template_response() 在視圖被完全執(zhí)行后調(diào)用,如果響應(yīng)實例有 render() 方法,表明它是一個 TemplateResponse 或等效對象。
它必須返回一個實現(xiàn)了 render 方法的響應(yīng)對象。它可以通過改變``response.template_name`` 和 response.context_data 來改變給定的 response ,或者它可以創(chuàng)建和返回全新的 TemplateResponse 或等效對象。
不需要顯式地渲染響應(yīng)——一旦所有模板中間件被調(diào)用,響應(yīng)會被自動渲染。
中間件會在響應(yīng)階段按照相反的順序運行,其中包括 process_template_response() 。
函數(shù)定義:
process_template_response(request, response)
request 是一個 HttpRequest 對象。
response 是 TemplateResponse 對象(或者等效對象),它通過 Django 視圖或中間件返回。
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse class myMinddle(MiddlewareMixin): def process_request(self, request): print("這是自定義中間件 請求1") def process_response(self,request, response): print("這是自定義中間件 響應(yīng)1") return response def process_view(self,request, view_func, view_args, view_kwargs): print("視圖函數(shù)之前執(zhí)行") def process_exception(self,request,exception): print("處理視圖函數(shù)")
訪問http://127.0.0.1:8000/testMinddle/
結(jié)果:
這是自定義中間件 請求1
視圖函數(shù)之前執(zhí)行
testMinddle
這是自定義中間件 響應(yīng)1
視圖函數(shù)出錯示例:
這是自定義中間件 請求1
視圖函數(shù)之前執(zhí)行
testMinddle
處理視圖函數(shù)錯誤
這是自定義中間件 響應(yīng)1
2.5新版本中間件寫法
官網(wǎng)上給的示例:
class SimpleMiddleware: def __init__(self, get_response): self.get_response = get_response # 配置和初始化 def __call__(self, request): # 在這里編寫視圖和后面的中間件被調(diào)用之前需要執(zhí)行的代碼,即process_request() response = self.get_response(request) # 在這里編寫視圖調(diào)用后需要執(zhí)行的代碼,即process_response() return response
案例:
使用官網(wǎng)上的寫法不用繼承 MiddlewareMixin
class SimpleMiddleware: def __init__(self, get_response): self.get_response = get_response # One-time configuration and initialization. def __call__(self, request): # Code to be executed for each request before # the view (and later middleware) are called. print("這是自定義中間件 SimpleMiddleware的請求") response = self.get_response(request) # Code to be executed for each request/response after # the view is called. print("這是自定義中間件 SimpleMiddleware的響應(yīng)") return response
執(zhí)行結(jié)果:
這是自定義中間件 SimpleMiddleware的請求
testMinddle
這是自定義中間件 SimpleMiddleware的響應(yīng)
注意
__init__(get_response)
中間件必須接受 get_response
參數(shù)。還可以初始化中間件的一些全局狀態(tài)。記住兩個注意事項:
- Django僅用 參數(shù)初始化您的中間件,因此不能定義 __init__() ,因為需要其他參數(shù)。
- 與每次請求都會調(diào)用 __call__() 方法不同,當(dāng) Web 服務(wù)器啟動后,__init__() 只被調(diào)用一次
上面只定義了process_request
和process_response
其中process_view
和process_exception
還是要寫。
class SimpleMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): print("這是自定義中間件 SimpleMiddleware的請求") response = self.get_response(request) print("這是自定義中間件 SimpleMiddleware的響應(yīng)") return response def process_view(self,request, view_func, view_args, view_kwargs): print("視圖函數(shù)之前執(zhí)行") def process_exception(self,request,exception): print("處理視圖函數(shù)錯誤")
3.Csrf中間件
使用Django
框架使用django.middleware.csrf.CsrfViewMiddleware
中間件,在前端頁面提交操作的時候,會報錯:
Forbidden (403) CSRF verification failed. Request aborted.
解決方法:
如果使用form提交,則在前端頁面里加入:
{% csrf_token %}
如:
<div> <form action="" method="post"> {% csrf_token %} <label>username: <input type="text" name="username"></label> <label>password:<input type="password" name="password"></label> <label><input type="submit" value="提交"></label> </form> </div> 如果是Ajax提交: """一定要導(dǎo)入jquery""" <body> <div> <label>username: <input type="text" name="username" id="user"></label> <label>password:<input type="password" name="password" id="pwd"></label> <input type="button" value="提交" id="btn"> </div> <script> $('#btn').click(function (){ $.ajax({ url: "", method: "post", data: {username: $('#user').val(), password: $('#pwd').val(), csrfmiddlewaretoken: '{{csrf_token}}'}, success: function (data) { console.log(data) } }) }) </script> </body> # 使用cookie: 使用cookie 則要導(dǎo)入"""jquery.cookie.min.js""" <script src="https://cdn.bootcdn.net/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js"></script> const csrftoken = $.cookie('csrftoken'); 使用: <body> <div> <label>username: <input type="text" name="username" id="user"></label> <label>password:<input type="password" name="password" id="pwd"></label> <input type="button" value="提交" id="btn"> </div> <script> $('#btn').click(function (){ const csrftoken = $.cookie('csrftoken'); $.ajax({ url: "", headers:{'X-CSRFToken': csrftoken}, // 加請求頭。 method: "post", data: {username: $('#user').val(), password: $('#pwd').val()}, success: function (data) { console.log(data) } }) }) </script> </body>
全局使用csrf局部函數(shù)使用,或全局不使用,局部函數(shù)使用csrf
from django.views.decorators.csrf import csrf_exempt,csrf_protect # 全局使用,局部不使用 @csrf_exempt def xxx() # 全局不使用(禁用掉),局部使用 @csrf_protect def yyy()
以上就是Django基礎(chǔ)CBV裝飾器和中間件的詳細內(nèi)容,更多關(guān)于Django基礎(chǔ)CBV裝飾器和中間件的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python實現(xiàn)多條件篩選Excel數(shù)據(jù)并批量繪制直方圖
這篇文章主要為大家介紹了如何Python對Excel數(shù)據(jù)進行多條件篩選和去除并批量繪制直方圖,文中的示例代碼講解詳細,感興趣的小伙伴可以參考一下2023-09-09對Pytorch中nn.ModuleList 和 nn.Sequential詳解
今天小編就為大家分享一篇對Pytorch中nn.ModuleList 和 nn.Sequential詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-08-08Python實現(xiàn)遍歷windows所有窗口并輸出窗口標(biāo)題的方法
這篇文章主要介紹了Python實現(xiàn)遍歷windows所有窗口并輸出窗口標(biāo)題的方法,涉及Python調(diào)用及遍歷windows窗口句柄的技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-03-03淺談Tensorflow 動態(tài)雙向RNN的輸出問題
今天小編就為大家分享一篇淺談Tensorflow 動態(tài)雙向RNN的輸出問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-01-01python詳解如何通過sshtunnel pymssql實現(xiàn)遠程連接數(shù)據(jù)庫
為了安全起見,很多公司服務(wù)器數(shù)據(jù)庫的訪問多半是要做限制的,由專門的DBA管理,而且都是做的集群,數(shù)據(jù)庫只能內(nèi)網(wǎng)訪問,所以就有一個直接的問題是,往往多數(shù)時候,在別的機器上(比如自己本地),是不能訪問數(shù)據(jù)庫的,給日常開發(fā)調(diào)試造成了很大不便2021-10-10python調(diào)用webservice接口的實現(xiàn)
這篇文章主要介紹了python調(diào)用webservice接口的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07詳解django的serializer序列化model幾種方法
序列化是將對象狀態(tài)轉(zhuǎn)換為可保持或傳輸?shù)母袷降倪^程。這篇文章主要介紹了詳解django的serializer序列化model幾種方法。具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-10-10