根據別人發布整理,個人愛好收集(原文:https://blog.csdn.net/mydistance/article/details/83958655 )
第一種:定義函數裝飾器,在函數,類中使用函數裝飾器
一、定義視圖類
定義類視圖,且類視圖繼承自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):
還可以列表方式並帶跳轉進行添加
@method_decorator([login_required(login_url='/login/'),],name='dispatch')
因為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')
第二種:定義類裝飾器,在函數,類中使用函數裝飾器
定義類裝飾器,在類中使用
class ShowClassName(object): def __init__(self, cls): self._cls = cls def __call__(self, a): print('class name:', self._cls.__name__) print('a name:', a) print(self._cls) return self._cls(a) class Foobar(object): def __init__(self, a): self.value = a def fun(self): print(self.value) Foobar=ShowClassName(Foobar) Foobar('woshiceshi').fun() #跟下面的使用方式是一樣的 class ShowClassName(object): def __init__(self, cls): self._cls = cls def __call__(self, a): print('class name:', self._cls.__name__) print('a name:', a) print(self._cls) return self._cls(a) @ShowClassName class Foobar(object): def __init__(self, a): self.value = a def fun(self): print(self.value) a = Foobar('woshiceshi') a.fun()
定義類裝飾器,在函數中使用 class ShowClassName(object): def __init__(self, cls): self._cls = cls def __call__(self, a): print('class name:', self._cls.__name__) print('a name:', a) print(self._cls) return self._cls(a) def func_ceshi(a): print(a) func_ceshi=ShowClassName(func_ceshi) func_ceshi('woshiceshi') #跟下面的使用是一樣的 class ShowClassName(object): def __init__(self, cls): self._cls = cls def __call__(self, a): print('class name:', self._cls.__name__) print('a name:', a) print(self._cls) return self._cls(a) @ShowClassName def func_ceshi(a): print(a) func_ceshi('woshiceshi')