【Django】在檢視類使用裝飾器的幾種方式
阿新 • • 發佈:2018-11-22
在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')
個人感覺,不是說哪種方法有什麼優劣之分,看你對規範,易讀,易維護,擴充套件性等的要求,選擇最合適的一個。