1. 程式人生 > >Django REST framework教程三: 基於類的檢視

Django REST framework教程三: 基於類的檢視

教程索引目錄

Django REST framework的系列教程
對於需要通篇瞭解的同學,可以點選教程索引目錄

其實,與其使用基於方法(function based)的檢視,我們更加傾向使用基於類(class based)的檢視。接下來,你將看到這是一個強大的模式,是我們能夠重用公共的功能,並且,幫我們保持程式碼DRY(Don’t Repeat Yourself)

使用基於類的檢視,重新API

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

from snippets.models import
Snippet from snippets.serializers import SnippetSerializer from django.http import Http404 from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status class SnippetList(APIView): """ 列出所有程式碼片段(snippets), 或者新建一個程式碼片段(snippet). """
def get(self, request, format=None): snippets = Snippet.objects.all() serializer = SnippetSerializer(snippets, many=True) return Response(serializer.data) def post(self, request, format=None): serializer = SnippetSerializer(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 SnippetDetail(APIView):
    """
    讀取, 更新 or 刪除一個程式碼片段(snippet)例項(instance).
    """
    def get_object(self, pk):
        try:
            return Snippet.objects.get(pk=pk)
        except Snippet.DoesNotExist:
            raise Http404

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

    def put(self, request, pk, format=None):
        snippet = self.get_object(pk)
        serializer = SnippetSerializer(snippet, 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):
        snippet = self.get_object(pk)
        snippet.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 snippets import views

urlpatterns = [
    url(r'^snippets/$', views.SnippetList.as_view()),
    url(r'^snippets/(?P<pk>[0-9]+)/$', views.SnippetDetail.as_view()),
]

urlpatterns = format_suffix_patterns(urlpatterns)

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

使用混入(mixins)

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

目前為止,我們所用的增刪改查操作,在我們建立的,任何支援模型的視圖裡,都沒有太大區別。這些通用的行為,在REST framework的混入(mixin)類中,都已經實現(implemented)了。

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

from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework import mixins
from rest_framework import generics

class SnippetList(mixins.ListModelMixin,
                  mixins.CreateModelMixin,
                  generics.GenericAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer

    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 建立了我們的檢視,並且加入了 ListModelMixinCreateModelMixin

基本類提供了核心的功能,而混入(mixin)類提供了 .list().create() 行為。然後,我們顯式地在 getpost 方法裡面,放入對應的行動。非常簡單,但目前夠用。

class SnippetDetail(mixins.RetrieveModelMixin,
                    mixins.UpdateModelMixin,
                    mixins.DestroyModelMixin,
                    generics.GenericAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer

    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 class)的檢視

使用混入(mixin)類重新檢視,相比之前,我們減少了一些程式碼,但我們還可以更進一步。REST framework提供了一套已經實現了混入類的通用(generic)檢視,我們可以使我們的 views.py 模組,更加瘦身!

from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework import generics


class SnippetList(generics.ListCreateAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer


class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer

哇噻~這下夠簡潔了。我們大獲自由,並且程式碼看起來像是很厲害的,乾淨的,地道的Django。

下一步,我們將移步教程第四部分(part 4 of the tutorial),將看看如何處理我們API的認證(authentication)和許可權(permissions)。

如果你覺得這個翻譯非常有幫助,不妨小額贊助我一下,你的認可,是我的動力!