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")
這種方式會裝飾所有方法,可以使用這種方式為方法添加多個裝飾器。