日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Django基礎CBV裝飾器和中間件的應用示例_python

作者:Hans_Wang ? 更新時間: 2022-05-24 編程語言

1. CBV加裝飾器

CBV加裝飾器有三種方法,

案例:要求登錄(不管get請求還是post請求)后才可以訪問

HTML代碼

index.html




    
    Title


Hello Index

login.html




    
    Title


username:

password:

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為具體要加的函數
@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?請求/響應處理的鉤子框架。它是一個輕量級的、低級的“插件”系統,用于全局改變?Django?的輸入或輸出。

每個中間件組件負責做一些特定的功能,Django中自帶了七個中間件

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',   #  安全中間件,為請求/響應周期提供了若干安全增強功能。每一項都可以通過設置獨立地啟用或禁用。
    'django.contrib.sessions.middleware.SessionMiddleware', # 啟用會話支持
    'django.middleware.common.CommonMiddleware', # “通用”中間件
    'django.middleware.csrf.CsrfViewMiddleware', # CSRF 保護中間件,通過在 POST 表單中添加隱藏的表單字段,并檢查請求的正確值,增加對跨站點偽造請求的保護。
    'django.contrib.auth.middleware.AuthenticationMiddleware', # 驗證中間件,將代表當前登錄的用戶的 user 屬性添加到每個傳入的 HttpRequest 對象中
    'django.contrib.messages.middleware.MessageMiddleware', # 消息中間件,啟用基于 cookie 和會話的消息支持
    'django.middleware.clickjacking.XFrameOptionsMiddleware', # X-Frame-Options 中間件,簡單的 通過 X-Frame-Options 頭的點擊劫持保護。
]

中間件(Middleware)在整個Djangorequest/response處理機制中的角色如下所示:

HttpRequest -> Middleware(request) -> View -> Middleware(response) -> HttpResponse

中間件常用于權限校驗、限制用戶請求、打印日志、改變輸出內容等多種應用場景.而且中間件對Django的輸入或輸出的改變是全局的。

Django?中間件作用:

  • 修改請求,即傳送到 view 中的 HttpRequest 對象。
  • 修改響應,即 view 返回的 HttpResponse 對象。

中間件執行順序:

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_requestprocess_response

在應用目錄下新建一個 py 文件,名字自定義。

在應用目錄下創建myMiddle.py
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("這是自定義中間件 響應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/
# 結果:
"""
這是自定義中間件 請求1
testMinddle
這是自定義中間件 響應1
"""

增加兩個自定義中間件,執行過程:

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("這是自定義中間件 響應1")
        return response
class myMinddle2(MiddlewareMixin):
    def process_request(self, request):
        print("這是自定義中間件 請求2")
    def process_response(self,request, response):
        print("這是自定義中間件 響應2")
        return response
setting.py:
MIDDLEWARE = [
    ......
    'wrapperMidd.myMinddle.myMinddle',
    'wrapperMidd.myMinddle.myMinddle2',
]
# 訪問:http://127.0.0.1:8000/testMinddle/
# 結果
"""
這是自定義中間件 請求1
這是自定義中間件 請求2
testMinddle
這是自定義中間件 響應2
這是自定義中間件 響應1
"""

如果在第一個中間件直接返回,執行順序如果:

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("這是自定義中間件 響應1")
        return response
class myMinddle2(MiddlewareMixin):
    def process_request(self, request):
        print("這是自定義中間件 請求2")
    def process_response(self,request, response):
        print("這是自定義中間件 響應2")
        return response
# 訪問:http://127.0.0.1:8000/testMinddle/
# 結果:
網頁上顯示:request
后臺顯示:
"""
這是自定義中間件 請求1
這是自定義中間件 響應1
"""

2.3 自定義中間件總結

自定義中間件先執行process_request再執行views.py里的視圖函數,最后再執行process_response,而且process_response函數必須要返回?return response

如果有多個自定義中間件,則執行順序按settings.py里自上而下執行,寫在上面的先執行。執行順序

自定義中間件1 process_request--->自定義中間件2 process_request-->視圖函數-->自定義中間件2 process_response -->自定義中間件1 process_response

如果自定義中間件的process_request里有return返回,而這個中間件還是在上面,則它會執行自己定義的process_requestprocess_response,則視圖函數和其他的中間件都不執行

如果自定義中間件的process_request里有return返回,而這個中間件上面還有其他的中間件,則會自上而下執行,執行到自定義中間件的process_request后就會執行process_response,則視圖函數和它下面的中間件都不執行

MIDDLEWARE = [
    ...其他中間件...
    '自定義中間件1',
    '自定義中間件2',  #  自定義中間件2里使用return直接返回 
    '自定義中間件3',
]
執行順序:
"""
其他中間件 process_request  --> 自定義中間件1 process_request --> 自定義中間件2 process_request --> 自定義中間件2 process_response --> 自定義中間件1 process_response -->其他中間件 process_response
"""
視圖函數和自定義中間件3是不執行的

2.4 其他中間件函數

process_view

process_view在process_request之后,路由轉發到視圖,執行視圖之前執行。
process_view() 只在 Django 調用視圖前被調用。它應該返回 None 或 HttpResponse 對象。如果它返回 None ,Django 將繼續處理這個請求,執行任何其他的 process_view() ,然后執行相應的視圖。如果它返回 HttpResponse 對象,Django 不會去影響調用相應的視圖;它會將響應中間件應用到 HttpResponse 并返回結果。
函數定義:
process_view(request, view_func, view_args, view_kwargs)
request 是一個 HttpRequest 對象。
view_func 是一個 Django 將要使用的 Python 函數。(這是一個真實的函數對象,不是函數的名稱);view_args 是一個用來傳遞給視圖的位置參數列表,;
view_kwargs 是一個用來傳遞給視圖的關鍵字參數字典。
view_args 和 view_kwargs 都不包含第一個視圖參數 ( request )。

process_exception

視圖執行中發生異常時執行。

當視圖引發異常時,Django 會調用 process_exception()。process_exception() 應該返回 None 或 HttpResponse 對象。如果它返回一個 HttpResponse 對象,模板響應和響應中間件將被應用且會將結果響應返回瀏覽器。否則,就會開始默認異常處理( default exception handling )。

再次,中間件在響應階段會按照相反的順序運行,其中包括 process_exception 。如果異常中間件返回一個響應,那么中間件之上的中間件類的 process_exception 方法根本不會被調用。

函數定義:
process_exception(request, exception)
request 是一個 HttpRequest 對象。 exception 是一個由視圖函數引發的 Exception 對象。

process_template_response

視圖函數剛執行完畢,process_response之前執行。

process_template_response() 在視圖被完全執行后調用,如果響應實例有 render() 方法,表明它是一個 TemplateResponse 或等效對象。

它必須返回一個實現了 render 方法的響應對象。它可以通過改變``response.template_name`` 和 response.context_data 來改變給定的 response ,或者它可以創建和返回全新的 TemplateResponse 或等效對象。

不需要顯式地渲染響應——一旦所有模板中間件被調用,響應會被自動渲染。

中間件會在響應階段按照相反的順序運行,其中包括 process_template_response() 。

函數定義:
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("這是自定義中間件 響應1")
        return response
    def process_view(self,request, view_func, view_args, view_kwargs):
        print("視圖函數之前執行")
    def process_exception(self,request,exception):
        print("處理視圖函數")
        

訪問http://127.0.0.1:8000/testMinddle/

結果:

這是自定義中間件 請求1
視圖函數之前執行
testMinddle
這是自定義中間件 響應1

視圖函數出錯示例:

這是自定義中間件 請求1
視圖函數之前執行
testMinddle
處理視圖函數錯誤
這是自定義中間件 響應1

2.5新版本中間件寫法

官網上給的示例:

class SimpleMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        # 配置和初始化
    def __call__(self, request):
        # 在這里編寫視圖和后面的中間件被調用之前需要執行的代碼,即process_request()
        response = self.get_response(request)
        # 在這里編寫視圖調用后需要執行的代碼,即process_response()
        return response

案例:

使用官網上的寫法不用繼承 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的響應")
        return response


執行結果:

這是自定義中間件 SimpleMiddleware的請求
testMinddle
這是自定義中間件 SimpleMiddleware的響應

注意

__init__(get_response)

中間件必須接受?get_response?參數。還可以初始化中間件的一些全局狀態。記住兩個注意事項:

  • Django僅用??參數初始化您的中間件,因此不能定義?__init__()?,因為需要其他參數。
  • 與每次請求都會調用?__call__()?方法不同,當 Web 服務器啟動后,__init__()?只被調用一次

上面只定義了process_requestprocess_response?其中process_viewprocess_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的響應")
        return response
    def process_view(self,request, view_func, view_args, view_kwargs):
        print("視圖函數之前執行")
    def process_exception(self,request,exception):
        print("處理視圖函數錯誤")

3.Csrf中間件

使用Django框架使用django.middleware.csrf.CsrfViewMiddleware中間件,在前端頁面提交操作的時候,會報錯:

Forbidden (403)
CSRF verification failed. Request aborted.

解決方法:

如果使用form提交,則在前端頁面里加入:

? ? {% csrf_token %}

如:

{% csrf_token %}
如果是Ajax提交: """一定要導入jquery"""
# 使用cookie: 使用cookie 則要導入"""jquery.cookie.min.js""" const csrftoken = $.cookie('csrftoken'); 使用:

全局使用csrf局部函數使用,或全局不使用,局部函數使用csrf

from django.views.decorators.csrf import csrf_exempt,csrf_protect
# 全局使用,局部不使用
@csrf_exempt
def xxx()
# 全局不使用(禁用掉),局部使用
@csrf_protect
def yyy()

原文鏈接:https://www.cnblogs.com/hans-python/p/16037470.html

欄目分類
最近更新