本文希望給大家提供一些思路,拋磚引玉。不要侷限於Django提供的手段,完全可以爲項目自己重新適合的裝飾器。
Django提供的內建的視圖用的裝飾器,個人認爲並不好用,它能很好的適合視圖函數,但是不能直接用在視圖類的方法上,歸根結底就是self的問題。
當URL映射到視圖函數時,第一個實參就是request,但是如果使用視圖類,那麼as_view()雖然分把類封裝的像函數一樣,但是調用函數時,使用的是類的實例即視圖實例。
也就是說as_view()內部本質上就是封裝類返回一個包裝函數view,每次URL請求來了就調用這個view函數,臨時創建視圖類實例,並使用self調用了dispatch調度到get或post等方法,在dispatch內部使用了getattr反射。
網上各種在視圖類cbv的dispatch函數加裝飾器的方法,個人認爲並不好。本文知識簡單處理,如果有空,下一篇文章將重新封裝自己寫的wrapper_method_before和wrapper_method_after裝飾器
from django.views.decorators.csrf import csrf_protect # csrf_protect就是強行在視圖函數前執行CsrfViewMiddleware,相當於臨時打開了CsrfViewMiddleware中間件 # from django.utils.decorators import method_decorator # 使用自己寫的裝飾器替換它 def wrapper_method_before(func): """在django的視圖裝飾器上面用""" from django.views import View def wrapper(*args, **kwargs): firstparam = args[0] if isinstance(firstparam, View): kwargs.update(viewinstance=firstparam) ret = func(*args[1:], **kwargs) else: ret = func(*args, **kwargs) return ret return wrapper def wrapper_method_after(func): """在django的視圖裝飾器下面用""" def wrapper(*args, **kwargs): view = kwargs.pop('viewinstance', None) if view is None: ret = func(*args, **kwargs) else: ret = func(view, *args, **kwargs) return ret return wrapper class PostView(View): @wrapper_method_before # 把視圖實例挪走 @csrf_protect # 必須csrf驗證通過 @wrapper_method_after # 把視圖實例挪回來 @login_required # 自己寫的裝飾器替換Django的,內部也修正了self的問題 def post(self, request: HttpRequest): pass