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_viewget 方法的引用。

類視圖使用裝飾器

可以使用裝飾器為類視圖增加功能,使用裝飾器有三種方式。

  • 在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")

這種方式會裝飾所有方法,可以使用這種方式為方法添加多個裝飾器。