使用基于类的视图重写API
我们首先将根视图重写为基于类的视图。所有这一切都涉及到重构views.py
。
from snippets.models import Snippet from snippets.serializers import SnippetSerializer from django.http import Http404 from rest_framework.views import APIView #APIView适用于CBV 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)
到现在为止还很好。它看起来与以前的情况非常相似,但是在不同的HTTP方法之间有了更好的分离。继续更新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)
看起来不错。它现在仍然非常类似于基于函数的视图。
我们还需要重构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)
好了,如果运行开发服务器,那么应该像以前那样工作。
Using mixins
使用基于类的视图的优势之一是 that it allows us to easily compose reusable bits of behaviour.
到目前为止,我们使用的创建/检索/更新/删除(create/retrieve/update/delete)操作将与我们创建的任何支持模型的API视图非常相似。这些常见的行为是在REST框架的mixin类中实现的。
我们来看看我们如何通过使用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() #queryset是GenericAPIView的属性。 serializer_class = SnippetSerializer #serializer_class是GenericAPIView的属性。 def get(self, request, *args, **kwargs): return self.list(request, *args, **kwargs) #list是ListModelMixin的方法。 def post(self, request, *args, **kwargs): return self.create(request, *args, **kwargs) #create是CreateModelMixin的方法。
我们会花点时间仔细检查这里发生的情况。我们正在使用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) #retrieve是RetrieveModelMixin的方法。
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs) #update是UpdateModelMixin的方法。
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs) #destroy是DestroyModelMixin的方法。
Pretty similar. Again we're using the GenericAPIView
class to provide the core functionality, and adding in mixins to provide the .retrieve()
, .update()
and .destroy()
actions.
Using generic class-based views
我们使用mixin类重写了这些视图,使用的代码比以前少一些,但我们可以进一步。REST框架提供了一组已经混合的通用视图,我们可以使用它来让views.py
模块更简化。
from snippets.models import Snippet from snippets.serializers import SnippetSerializer from rest_framework import generics class SnippetList(generics.ListCreateAPIView): #get封装到ListCreateAPIView中了。 queryset = Snippet.objects.all() serializer_class = SnippetSerializer class SnippetDetail(generics.RetrieveUpdateDestroyAPIView): #get、put、delete都封装到RetrieveUpdateDestroyAPIView中了。 queryset = Snippet.objects.all() serializer_class = SnippetSerializer
更简洁了!