从介绍Django快开始,咱们就一直在使用FBV的方式来撰写代码,两者本质上并无太大的区别,然而到了REST framework,更会倾向于用CBV来写API的视图,后面会看到这个方式的强大,它容许咱们重用经常使用的功能,让代码更简练。django
如今开始撰写一个简单的CBV代码,打开app内的views.py文件app
from rest_framework import status from rest_framework.response import Response from rest_framework.views import APIView from django.http import Http404 from app01.models import Snippet from app01.serializers import SnippetSerializer class SnippetList(APIView): """ 列出全部的对象或者建立一个新的对象 """ 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方法间更好的分离,来更新一下上述实例的代码,仍是在app的views.py文件。post
class SnippetDetail(APIView): """ 获取、更新、删除一个实例对象 """ 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)
这段代码看起来很棒,可是它如今仍是跟FBV的代码很像。url
同时,还须要稍微重构app内的urls文件,如今须要用CBV的方式。spa
from app01 import views from django.urls import path, include from rest_framework.urlpatterns import format_suffix_patterns urlpatterns = [ path('snippets/', views.SnippetList.as_view()), path('snippets/<int:pk>/', views.SnippetDetail.as_view()), ] urlpatterns = format_suffix_patterns(urlpatterns)
好了,咱们已经完成了。若是你将代码容许起来,应该跟以前的效果同样。rest
使用CBV的的最大优势之一就是,它容许咱们很容易的编写一些可重用的行为。code
到目前为止,建立、删除、更新、获取这些操做在任何模型支持的API视图中都是很是类似的。orm
一块儿来看下,如何使用mixin类来构建视图。再次修改view.py文件对象
from app01.models import Snippet from app01.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和CreateModelMixinblog
基类提供了核心的功能,mixin类提供了.list()和.create()操做。而后,明确的绑定了get和post方法到合适的行为。到目前为止,足够简单。
继续改造另外一个CBV
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)
跟上面的CBV很是类似。一样的,咱们再一次使用GenericAPIView来提供核心代码,而后使用mixin中的.retrieve(), .update(), .destory()方法。
上面使用mixin类使用比以前更少的代码稍微重写了视图,可是咱们还能更上一层楼。REST framework提供了一系列已经混合封装好的generic视图,进而能够直接在views.py文件内简化使用。
from app01.models import Snippet from app01.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
看到这里,难免会惊叹,OMG!这也太简洁了。咱们免费获得了大量的代码,咱们的代码看起来很好,很干净,很符合语言习惯的Django。