咱們也可使用基於類的視圖編寫咱們的API視圖,而不是基於函數的視圖。咱們將看到這是一個強大的模式,容許咱們重用經常使用功能,並幫助咱們保持代碼DRY。html
使用基於類的視圖重寫咱們的API
咱們將首先將根視圖重寫爲基於類的視圖。全部這一切都涉及到一些重構views.py。django
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): # APIView實際繼承django總的View # from django.views.generic import View """ # 這裏是SnippetList接口描述 List all snippets, or create a new snippet. """ def get(self, request, format=None): snippets = Snippet.objects.all() # manay=True 用於querySet對象 serializer = SnippetSerializer(snippets, many=True) 3 Respone比django的response更強大 return Response(serializer.data) def post(self, request, format=None): serializer = SnippetSerializer(data=request.data) if serializer.is_valid(): # .save()是調用SnippetSerializer中的create()方法 serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
到如今爲止還挺好。它看起來與之前的狀況很是類似,可是咱們在不一樣的HTTP方法之間有更好的分離。咱們還須要更新實例視圖views.py。segmentfault
class SnippetDetail(APIView): """ Retrieve, update or delete a 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
使用基於類視圖的最大好處之一就是讓咱們輕鬆地組合可重用的行爲。post
到目前爲止,咱們使用的建立/查看/更新/刪除操做與咱們建立的任何支持模型的API視圖類似。這些常見的行爲是在REST框架的mixin類中實現的。url
咱們來看看咱們如何使用mixin類編寫視圖。這是咱們的views.py模塊了。rest
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): # mixins.CreateModelMixin 能夠保存數據 # generics.GenericAPIView 繼承了APIView queryset = Snippet.objects.all() serializer_class = SnippetSerializer def get(self, request, *args, **kwargs): # self.list是ListModelMixin的list函數 # 功能是過濾、分頁、調用serializer,將數據序列化 return self.list(request, *args, **kwargs) def post(self, request, *args, **kwargs): return self.create(request, *args, **kwargs)
咱們會花一點時間仔細檢查這裏發生的狀況。咱們用GenericAPIView建一個視圖,並在加ListModelMixin和CreateModelMixin。code
基類提供核心功能,而mixin類提供.list()和.create()操做。咱們明確綁定get和post方法。到目前爲止足夠簡單的東西
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類來提供核心功能,並增長提供.retrieve(),.update()和.destroy()方法。
使用泛型類視圖
使用mixin類,咱們重寫了這些視圖,使用的代碼比之前少得多,可是咱們能夠進一步。REST框架提供了一組已經混合的通用視圖,咱們可使用它來修剪咱們的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。
接下來,咱們將介紹本教程的第4部分,咱們將在此介紹如何處理API的身份驗證和權限。
Django REST FrameWork中文文檔目錄:
Django REST FrameWork 中文教程1:序列化
Django REST FrameWork 中文教程2:請求和響應
Django REST FrameWork 中文教程3:基於類的視圖
Django REST FrameWork 中文教程4:驗證和權限
Django REST FrameWork 中文教程5:關係和超連接API