1. 程式人生 > >Django REST framework 中 3 種類視圖的對比

Django REST framework 中 3 種類視圖的對比

互聯網 運維 web開發 python

相較於使用基於方法(function based)的視圖,我們更加傾向使用基於類(class based)的視圖。接

下來,你將看到這是一個強大的模式,是我們能夠重用公共的功能,並且,幫我們減少重復的造輪子。

我們現在開始了。首先,重寫根視圖(root view),變成基於類的視圖。所涉及的,只是對 views.py 文件的一點重構。


使用基於 APIView 類的視圖

from testapps.models import Testapp
from testapps.serializers import TestappSerializer
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status

class TestappList(APIView):
"""
列出所有代碼片段(testapps), 或者新建一個代碼片段(testapp).
"""
    def get(self, request, format=None):
        testapps = Testapp.objects.all()
        serializer = TestappSerializer(testapps, many=True)
        return Response(serializer.data)

    def post(self, request, format=None):
        serializer = TestappSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


至此為止,一切順利。看起來,跟基於方法的差別不大,但我們將各個 HTTP 請求方法之間,做了更好的分離。接著,我們將同樣的更改我們,處理片段詳細的視圖,繼續我們的 views.py 文件:

class TestappDetail(APIView):

至此為止,一切順利。看起來,跟基於方法的差別不大,但我們將各個 HTTP 請求方法之間,做了更

好的分離。接著,我們將同樣的更改我們,處理片段詳細的視圖,繼續我們的 views.py 文件:


class TestappDetail(APIView):

"""
讀取, 更新 or 刪除一個代碼片段(testapp)實例(instance).
"""
    def get_object(self, pk):
        try:
            return Testapp.objects.get(pk=pk)
        except Testapp.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        testapp = self.get_object(pk)
        serializer = TestappSerializer(testapp)
        return Response(serializer.data)

    def put(self, request, pk, format=None):
        testapp = self.get_object(pk)
        serializer = TestappSerializer(testapp, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk, format=None):
        testapp = self.get_object(pk)
        testapp.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)


看起來不錯。但還是跟基於方法的視圖,差別不多。


我們也需要重構 urls.py文件,因為我們現在使用的是基於類的視圖。


from django.conf.urls import url
from rest_framework.urlpatterns import format_suffix_patterns
from testapp import views

urlpatterns = [
    url(r‘^testapp/$‘, views.TestappList.as_view()),
    url(r‘^testapp/(?P<pk>[0-9]+)/$‘, views.TestappDetail.as_view()),
]

urlpatterns = format_suffix_patterns(urlpatterns)


好,搞定。如果你跑起開發者服務器,應該跟之前的效果是一樣的。


使用 Mixins 類的視圖


使用類視圖的一大好處是,我們可以很容易地,組成可重復使用的行為。

目前為止,我們所用的增刪改查操作,在我們創建的,任何支持模型的視圖裏,都沒有太大區別。這些

通用的行為,在 REST framework的 Mixin類中,都已經實現了。

讓我們看看,使用混合類,如何組建視圖。下面同樣是我們的 views.py 模塊:


from testapp.models import Testapp
from testapp.serializers import Testapperializer
from rest_framework import mixins
from rest_framework import generics

class TestappList(mixins.ListModelMixin,
                  mixins.CreateModelMixin,
                  generics.GenericAPIView):
    queryset = Testapp.objects.all()
    serializer_class = Testapperializer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)


我們會花一些時間來審查一下,這裏發生的事情。我們使用 GenericAPIView 創建了我們的視圖,並且

加入了 ListModelMixin 和 CreateModelMixin 。


基本類提供了核心的功能,Mixin 類提供了 .list() 和 .create() 行為。然後,我們顯式地在 get

和 post 方法裏面,放入對應的行動。非常簡單,但目前夠用。


class TestappDetail(mixins.RetrieveModelMixin,
                    mixins.UpdateModelMixin,
                    mixins.DestroyModelMixin,
                    generics.GenericAPIView):
    queryset = Testapp.objects.all()
    serializer_class = TestappSerializer

    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)


非常的類似。我們使用了 GenericAPIView 類提供了核心功能,而 Mixin 類提供了 .retrieve()

,.update() 和 .destroy() 行為。


使用 Generic 類的視圖


使用混 Mixin 類重新視圖,相比之前,我們減少了一些代碼,但我們還可以更進一步。REST framework


提供了一套已經實現了 Mixin 類的 Generic 視圖,我們可以使我們的 views.py 模塊,更加瘦身!


from testapps.models import Testapp
from testapps.serializers import TestappSerializer
from rest_framework import generics

class TestappList(generics.ListCreateAPIView):
    queryset = Testapp.objects.all()
    serializer_class = TestappSerializer

class TestappDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Testapp.objects.all()
    serializer_class = TestappSerializer


哇噻~這下夠簡潔了。代碼看起來像是很厲害的,幹凈的,地道的 Django。


本文出自 “Python & Golang 學習” 博客,請務必保留此出處http://51reboot.blog.51cto.com/2180875/1981779

Django REST framework 中 3 種類視圖的對比