Django REST framework 中 3 種類視圖的對比
相較於使用基於方法(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 種類視圖的對比