教程3:基于類的視圖
我們也可以使用基于類的視圖來編寫我們的API視圖,而不是基于功能的視圖痒芝。正如我們將看到的俐筋,這是一個(gè)強(qiáng)大的模式,使我們可以重用常用功能严衬,并幫助我們保持代碼干爽澄者。
使用基于類的視圖重寫我們的API
我們首先將根視圖重寫為一個(gè)基于類的視圖。這一切都涉及到一些重構(gòu)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):
"""
List all snippets, or create a new 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)在為止還挺好粱挡。它和前面的例子看起來很相似,但是我們?cè)诓煌腍TTP方法之間有更好的分離俄精。我們還需要更新中的實(shí)例視圖views.py
询筏。
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)
這看起來不錯(cuò)。同樣竖慧,它現(xiàn)在仍然與基于功能的視圖非常相似嫌套。
我們snippets/urls.py
現(xiàn)在還需要稍微重構(gòu)我們使用基于類的視圖。
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ùn)行開發(fā)服務(wù)器,一切都應(yīng)該像以前一樣工作砍的。
使用mixin
使用基于類的視圖的一個(gè)重大勝利是它允許我們輕松地構(gòu)造可重復(fù)使用的行為痹筛。
到目前為止,我們使用的創(chuàng)建/檢索/更新/刪除操作對(duì)于我們創(chuàng)建的任何模型支持的API視圖將非常相似。這些常見的行為是在REST框架的mixin類中實(shí)現(xiàn)的谣旁。
我們來看看如何使用mixin類來構(gòu)建視圖。這是我們的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)
我們將花一點(diǎn)時(shí)間仔細(xì)檢查這里發(fā)生的事情。我們正在建立我們的觀點(diǎn)瘟判,使用GenericAPIView
和添加ListModelMixin
和CreateModelMixin
。
基類提供核心功能角溃,mixin類提供.list()
和.create()
操作。然后减细,我們明確地將方法get
和post
方法綁定到適當(dāng)?shù)牟僮鳌5侥壳盀橹棺銐蚝?jiǎn)單未蝌。
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()
行動(dòng)。
使用通用的基于類的視圖
使用mixin類纸型,我們重寫了視圖拇砰,使用比以前稍少的代碼,但是我們可以更進(jìn)一步狰腌。REST框架提供了一組已經(jīng)混合的通用視圖除破,我們可以使用它們更多地修剪我們的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
哇琼腔,這很簡(jiǎn)潔瑰枫。我們已經(jīng)獲得了大量的免費(fèi),而且我們的代碼看起來很好展姐,干凈躁垛,慣用的Django。
接下來圾笨,我們將進(jìn)入本教程的第4部分教馆,在這里我們將看看如何處理我們的API的身份驗(yàn)證和權(quán)限。