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
建立了我們的檢視,並且加入了 ListModelMixin
和 CreateModelMixin
。
基本類提供了核心的功能,而混入(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
類提供了核心功能,而混入(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)。
如果你覺得這個翻譯非常有幫助,不妨小額贊助我一下,你的認可,是我的動力!