1. 程式人生 > >【Django】在檢視類使用裝飾器的幾種方式

【Django】在檢視類使用裝飾器的幾種方式

在Django中,檢視中的類稱為類檢視,個人喜歡把檢視中的類叫做檢視類,函式叫做檢視函式,一種習慣而已。

一、定義檢視類

定義類檢視,且類檢視繼承自View(舉例)

from django.views.generic import View

class DemoView(View):

        """
    具體的檢視函式
        """

定義路由:

urlpatterns = [
    # 類檢視:註冊
    url(r'^register/$',views.DemoView.as_view()),
]

類檢視的好處:
程式碼可讀性好,類檢視相對於函式檢視有更高的複用性

二、檢視類使用裝飾器:

定義一個裝飾器:

def my_decorator(func):
    
    def wrapper(request, *args, **kwargs): 
        print('自定義裝飾器被呼叫了')
        print('請求路徑%s' % request.path)        
        return func(request, *args, **kwargs) 
    return wrapper

方法一:在url配置中裝飾:

urlpatterns = [
    # 我們在路由部分, 把定義好的裝飾器新增到當前的函式上
    # 這裡需要注意: as_view() 會返回一個 view() 函式
    # 所以我們把裝飾器新增到view()函式上.
    url(r'^demo/$', views.my_decorate(views.DemoView.as_view()))
]

弊端:單看檢視的時候,無法知道此檢視還被添加了裝飾器,不利於程式碼的完整性;此種方法會為類檢視中的所有請求方法都加上裝飾器行為

方法二:呼叫系統的裝飾器(給某個檢視函式新增裝飾器)
需要使用method_decorator將其轉換為適用於類檢視方法的裝飾器,這種方法直接將裝飾器應用在了具體的檢視函式上,哪個檢視函式需要,就給他新增。

@method_decorator(my_decorator)
def get(self, request):
    print('get方法')
    return HttpResponse('ok')

方法三:在類上面新增(給所有的檢視函式都新增裝飾器)

@method_decorator(my_decorator, name='dispatch')
class DemoView(View):

因為dispatch方法被 as_view() 中的 view() 呼叫,所以我們對這個方法新增裝飾器, 也就相當於對整個類檢視的方法新增裝飾器。

方法四:定義裝飾器時,新增一個self引數

裝飾器如下:

def my_decorator(func):
    # 此處增加了self
    def wrapper(self, request, *args, **kwargs): 
        print('自定義裝飾器被呼叫了')
        print('請求路徑%s' % request.path)
        # 此處增加了self
        return func(self, request, *args, **kwargs) 
    return wrapper

使用:直接用自定義裝飾器裝飾在函式檢視上

    @my_decorator
    def get(self, request):
        print('get方法')
        return HttpResponse('ok')

方法五:用Mixin擴充套件類的形式,繼承多個裝飾器,併為類檢視中的所有函式檢視新增裝飾行為

假設定義了兩個裝飾器@my_decorator和@my_decorator2

# 第一個擴充套件類, 讓他繼承自
object class BaseView(object): 
    @classmethod 
    def as_view(cls, *args, **kwargs): 
        view = super().as_view(*args, **kwargs) 
        view = my_decorator(view) 
        return view 
# 第二個擴充套件類,讓他繼承自object 
class Base2View(object): 
    @classmethod 
    def as_view(cls, *args, **kwargs): 
        view = super().as_view(*args, **kwargs) 
        view = my_decorator2(view) 
        return view 
# 類檢視, 讓他除了繼承自這兩個父類外, 最後繼承View類. 
class DemoView(BaseView, Base2View,View): 
    def get(self, request): 
        print('get方法') 
        return HttpResponse('ok') 
    def post(self, request): 
        print('post方法') 
        return HttpResponse('ok')

個人感覺,不是說哪種方法有什麼優劣之分,看你對規範,易讀,易維護,擴充套件性等的要求,選擇最合適的一個。