我們也可以使用基于類的視圖編寫我們的API視圖,而不是基于函數(shù)的視圖。我們將看到這是一個強大的模式,允許我們重用常用功能,并幫助我們保持代碼DRY。
我們將首先將根視圖重寫為基于類的視圖。所有這些都是對views.py文件的重構(gòu)。
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或者創(chuàng)建一個新的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)
到現(xiàn)在為止還挺好。它看起來與以前的情況非常相似,但是我們在不同的HTTP方法之間有更好的分離。我們還需要更新views.py中的實例視圖。
class SnippetDetail(APIView):
"""
檢索,更新或刪除一個snippet示例。
"""
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)
看起來不錯,它現(xiàn)在仍然非常類似于基于功能的視圖。
我們還需要重構(gòu)我們的urls.py,現(xiàn)在我們使用基于類的視圖。
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)
好了,我們完成了。如果你啟動服務,那么它應??該像之前一樣可以運行。
使用基于類視圖的最大優(yōu)勢之一是它可以輕松地創(chuàng)建可復用的行為。
到目前為止,我們使用的創(chuàng)建/獲取/更新/刪除操作和我們創(chuàng)建的任何基于模型的API視圖非常相似。這些常見的行為是在REST框架的mixin類中實現(xiàn)的。
讓我們來看看我們是如何通過使用mixin類編寫視圖的。這是我們的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)
我們將花點時間好好看下這里的具體實現(xiàn)方式。我們使用GenericAPIView構(gòu)建了我們的視圖,并且用上了ListModelMixin和CreateModelMixin。
基類提供核心功能,而mixin類提供.list()和.create()操作。然后我們明確地將get和post方法綁定到適當?shù)牟僮?。都目前為止都是顯而易見的。
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類來提供核心功能,并添加mixins來提供.retrieve()),.update()和.destroy()操作。
通過使用mixin類,我們使用更少的代碼重寫了這些視圖,但我們還可以再進一步。REST框架提供了一組已經(jīng)混合好(mixed-in)的通用視圖,我們可以使用它來簡化我們的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
哇,如此簡潔。我們可以使用很多現(xiàn)成的代碼,讓我們的代碼看起來非常清晰、簡潔,地道的Django。
接下來,我們將移步教程的第4部分,我們將介紹如何處理API的身份驗證和權(quán)限。
更多建議: