django的類視圖-11
- 2020 年 1 月 19 日
- 筆記
目錄
使用函數方式定義的視圖叫函數視圖,雖然使用方便,便於理解,但是當一個s視圖有多種請求方式的時候,變需要使用分支來編寫不同請求方式對應的邏輯。
使用函數視圖,程式碼看上去是這樣子的
def my_view(request): if request.method == 'GET': return HttpResponse("get") if request.method == 'POST': return HttpResponse("post")1. 使用類視圖
基於類的視圖的核心是允許你用不同的實例方法來響應不同的HTTP請求方法,而不是在一個視圖函數中使用條件分支程式碼來實現。
創建類視圖
使用類視圖,程式碼是這樣子的
from django.views import View class ClassView(View): def get(self, request): return HttpResponse("get") def post(self, request): return HttpResponse("post")類視圖需要繼承django提供的 View 類,使用 from django.views import View 導入
註冊路由
配置類視圖的時候,使用類視圖的 as_view 方法註冊路由
urlpatterns = [ url(r'^class_view', views.ClassView.as_view(), name="class_view") ]
as_view 會返回類中一個方法的引用,它會到 View 中,執行 dispatch 方法, dispatch 會方法會在類中查找類似GETPOST之類的類方法,然後和請求方式進行匹配,匹配上了,就返回該方法的引用。
如果向上邊的類視圖發送一個 GET 請求,他會把 GET 轉換為小寫形式並和類中的方法進行匹配,然後匹配到 get 方法,會把 get 方法的引用返回到 as_view 調用處。所以在 get 請求下最後 as_view 是 get 方法的引用。
類視圖使用裝飾器
可以使用裝飾器為類視圖增加功能,使用裝飾器有三種方式。
- 在url配置中裝飾
- 在類視圖中裝飾
- 使用Mixin擴展類
為了便於理解,使用下邊的案例做演示
def decorator(func): def wrapper(request, *args, **kwargs): print('裝飾器被調用') return func(request, *args, **kwargs) return wrapper class ClassView(View): def get(self, request): return HttpResponse("get") def post(self, request): return HttpResponse("post")在url中裝飾
url(r'^class_view', views.decorator(views.ClassView.as_view()), name="class_view")
發送 GET 或者 POST 類型請求列印結果
裝飾器被調用
在url中調用該函數,並把 as_view 方法傳入即可,這種方式會把所有被請求的函數都進行裝飾。
這種方法把裝飾放到了url配置中,不利於程式碼的完整性和可讀性,所以一般情況下不使用。
在類視圖中裝飾
在類視圖中使用裝飾器不能直接裝飾,需要使用 method_decorator 把裝飾器轉換位適用於類的裝飾器。
在我們寫的裝飾器中,內層函數接收的參數為 request
def decorator(func): def wrapper(request, *args, **kwargs): print('裝飾器被調用') return func(request, *args, **kwargs) return wrapper而在類視圖的方法中,第一個參數是 self ,所以要使用 method_decorator 把裝飾器的第一個參數補充為 self 以使用類視圖中的方法。
也可以手動為裝飾器添加參數 self
def decorator(func): def wrapper(self, request, *args, **kwargs): print('裝飾器被調用') return func(self, request, *args, **kwargs) return wrapper裝飾所有方法
可以重寫並裝飾類的 dispatch 方法,程式碼如下
class ClassView(View): @method_decorator(decorator) def dispatch(self, request, *args, **kwargs): return super().dispatch(request, *args, **kwargs) def get(self, request): return HttpResponse("get") def post(self, request): return HttpResponse("post")使用 GET 或者 POST 方式請求,都會執行裝飾器,列印結果
裝飾器被調用
只裝飾某一個方法
class ClassView(View): @method_decorator(decorator) def get(self, request): return HttpResponse("get") def post(self, request): return HttpResponse("post")只有使用 GET 方式請求,才會執行裝飾器,列印結果
裝飾器被調用
POST 方式不會執行裝飾器。
method_decorator 的 name 參數
裝飾全部方法
@method_decorator(decorator, name="dispatch") class ClassView(View): def get(self, request): return HttpResponse("get") def post(self, request): return HttpResponse("post")指定被裝飾的方法
@method_decorator(decorator, name="get") class ClassView(View): def get(self, request): return HttpResponse("get") def post(self, request): return HttpResponse("post")使用Mixin擴展類
擴展類使用了 Python 多繼承的 MRO 特性。
class MyMixin(object): @classmethod def as_view(cls, *args, **kwargs): view = super().as_view(*args, **kwargs) view = decorator(view) return view class ClassView(MyMixin, View): def get(self, request): return HttpResponse("get") def post(self, request): return HttpResponse("post")這種方式會裝飾所有方法,可以使用這種方式為方法添加多個裝飾器。

