1. 程式人生 > >Django類檢視解析

Django類檢視解析

以函式的方式定義的檢視稱為函式檢視,函式檢視便於理解。但是遇到一個檢視對應的路徑提供了多種不同HTTP請求方式的支援時,便需要在一個函式中編寫不同的業務邏輯,程式碼可讀性與複用性都不佳。

在Django中也可以使用類來定義一個檢視,稱為類檢視。

類檢視的優點:程式碼可讀性好、程式碼的複用性更高,如果其他地方需要用到類檢視的某個特定邏輯,直接繼承該類檢視即可。

使用類檢視可以將檢視對應的不同請求方式以類中的不同請求方法來區別定義,如:

from django.views.generic import View

class RegisterView(View):
    """類檢視:處理註冊"""

    def get(self, request):
        """處理GET請求,返回註冊頁面"""
        return render(request, 'register.html')

    def post(self, request):
        """處理POST請求,實現註冊邏輯"""
        return HttpResponse('這裡實現註冊邏輯')

定義類檢視需要繼承自Django提供的父類View,使用from django.views.generic import view

配置路由時,使用類檢視的as_view()方法來新增

from django.conf.urls import url
from . import views

urlpatterns = [
    #類檢視路由
    url(r'^register/$',views.RegisterView.as_view()),
]

分析類檢視原理

@classonlymethod
    def as_view(cls, **initkwargs):
        """
        Main entry point for a request-response process.
        """
        ...省略程式碼...

        def view(request, *args, **kwargs):
            # 2 生成RegisterView的類物件
            self = cls(**initkwargs)
            if hasattr(self, 'get') and not hasattr(self, 'head'):
                self.head = self.get
            self.request = request
            self.args = args
            self.kwargs = kwargs
            # 3 呼叫dispatch方法,按照不同請求方式呼叫不同請求方法
            return self.dispatch(request, *args, **kwargs)

        ...省略程式碼...

        # 1 views.RegisterView.as_view()返回真正的函式檢視
        return view

    # 根據請求方法的小寫形式執行同名的函式
    def dispatch(self, request, *args, **kwargs):
        # Try to dispatch to the right method; if a method doesn't exist,
        # defer to the error handler. Also defer to the error handler if the
        # request method isn't on the approved list.
        if request.method.lower() in self.http_method_names:
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
        else:
            handler = self.http_method_not_allowed
        return handler(request, *args, **kwargs)

裝飾類檢視函式

在類檢視中使用為函式檢視準備的裝飾器時,不能直接新增裝飾器,需要使用method_decorator將其轉換為適用於類檢視方法的裝飾器

method_decorator裝飾器使用name引數指明被裝飾的方法

from django.utils.decorators import method_decorator

# 為全部請求方法新增裝飾器
@method_decorator(my_decorator, name='dispatch')
class DemoView(View):
    def get(self, request):
        print('get方法')
        return HttpResponse('ok')

    def post(self, request):
        print('post方法')
        return HttpResponse('ok')


# 為特定請求方法新增裝飾器
@method_decorator(my_decorator, name='get')
class DemoView(View):
    def get(self, request):
        print('get方法')
        return HttpResponse('ok')

    def post(self, request):
        print('post方法')
        return HttpResponse('ok')

如果需要為類檢視的多個方法新增裝飾器,但又不是所有的方法(為所有方法新增裝飾器參考上面例子),可以直接在需要新增裝飾器的方法上使用method_decorator,可參考以下示例程式碼

from django.utils.decorators import method_decorator

# 為特定請求方法新增裝飾器
class DemoView(View):

    @method_decorator(my_decorator)  # 為get方法添加了裝飾器
    def get(self, request):
        print('get方法')
        return HttpResponse('ok')

    @method_decorator(my_decorator)  # 為post方法添加了裝飾器
    def post(self, request):
        print('post方法')
        return HttpResponse('ok')

    def put(self, request):  # 沒有為put方法新增裝飾器
        print('put方法')
        return HttpResponse('ok')

類檢視Mixin擴充套件類

使用面向物件多繼承的特性,可以通過定義父類(作為擴充套件類),在父類中定義想要向類檢視補充的方法,類檢視繼承這些擴充套件父類,便可實現程式碼複用。定義的擴充套件父類名稱通常以Mixin結尾。可參考如下程式碼

class ListModelMixin(object):
    """
    list擴充套件類
    """
    def list(self, request, *args, **kwargs):
        ...

class CreateModelMixin(object):
    """
    create擴充套件類
    """
    def create(self, request, *args, **kwargs):
        ...

class BooksView(CreateModelMixin, ListModelMixin, View):
    """
    同時繼承兩個擴充套件類,複用list和create方法
    """
    def get(self, request):
        self.list(request)
        ...

    def post(self, request):
        self.create(request)
        ...

class SaveOrderView(CreateModelMixin, View):
    """
    繼承CreateModelMixin擴充套件類,複用create方法
    """
    def post(self, request):
        self.create(request)
        ...