我们也能使用类视图代替函数视图来写API视图.这是一个强大的功能,能够重用代码,是代码DRY(don’t repeat yourself).
我们开始将根视图重写为类视图.只需要稍微重构下views.py就行了.
from snippets.models import Snippet
from snippets.serializers import SnippetSerailizer
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):
'''
列出所有snippet,或者创建一个新的snippet
'''
def get(self, request, fromat=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方法.We’ll also need to update the instance view in 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)
看起来不错.还是和视图函数很像.我们还要重构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[0-9]+)/$' , views.SnippetDetail.as_view())
]
urlpatterns = format_suffix_patterns(urlpatterns)
ok,完成.如果你运行开发服务器,一切都和之前一样工作.
使用视图类的一个好处是我们可以很容易的复用代码.
我们使用的CRUD方法和我们写的model-backed API视图很像.这些共同的行为(behaviour)在REST framework的混合类(mixin class)中有实现.
接下来让我们看看怎么使用混合类来写视图.这是我们的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 = SnippetSerialier
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来构建视图,还加入了CreateModelMixin和ListModelMixin.
基类提供了核心功能,mixin类提供了.list()和.create()操作.然后我们显式的将get和post方法绑定了合适的操作.到此为止,都很简单.
class SnippetDetail(mixins.RetrieveModelMixin,
mixin.UpdateModelMixin,
mixin.DestoryModelMixin,
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.destory(request, *args, **kwargs)
非常相似.我们使用GenericAPIView类来提供核心功能,使用mixins来提供.retrieve(), .update(),和.destory()操作.
使用mixins我们能用更少的代码重写视图,但是我们可以更进一步.REST framework提供了一组已经mixed-in 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.RetrieveUpdateDestoryAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
WOW,这真简洁.我们可以省很多时间,而且我们的代码看起来像良好,干净的,通顺的Django.
接下来的指南(4),我们将会看一下怎么为我们的API做权限和验证.