我们在三级视图中,由于获取所有数据和获取一条数据都是使用GET请求,而二级视图(三级视图)只允许有一个get方法,因此我们在两个类中进行了设计,并且这样刚好将路由分开。而视图集则提供了新的路由和方法集合,来使我们将路由整合起来,方法整合起来。
该类继承自APIView,我们可以使用任何标准属性(如permission_classes,authentication_classes)来控制视图集上的API。ViewSet不提供任何操作的实现。为了使用该类,必须重写该类并显式定义操作实现。
通常,我们不会使用该类。因为需要全部重写。
如果要使用ViewSet,那么将要重写下面的所有方法,这并不比APIView高明多少,但是当你的业务非常复杂的时候,确实可以选择重写ViewSet来实现最大的灵活性。
class BookViewSet(viewsets.ViewSet):
def list(self, request):
pass
def create(self, request):
pass
def retrieve(self, request, pk=None):
pass
def update(self, request, pk=None):
pass
def partial_update(self, request, pk=None):
pass
def destroy(self, request, pk=None):
pass一个ViewSet类同时提供以下可用属性
# views.py
class BookViewSet(ViewSet):
def list(self,request):
queryset = BookInfo.objects.all()
serializer = BookInfoSerializer(queryset,many=True)
return Response(serializer.data)
def retrieve(self,request,pk=None):
queryset = BookInfo.objects.all()
user = get_object_or_404(queryset, pk=pk)
serializer = BookInfoSerializer(user)
return Response(serializer.data)
# urls.py
urlpatterns = [
path('bookviewset/', BookViewSet.as_view({'get': 'list'})),
path('bookviewset/<int:pk>', BookViewSet.as_view({'get': 'retrieve'})),
]GenericViewSet继承自GenericAPIView,作用也与GenericAPIVIew类似,提供了get_object、get_queryset等方法便于列表视图与详情信息视图的开发。在GenericAPIView中,没有提供任何动作action方法,需要我们自己覆盖该类并混合所需的混合类,或者明确定义操作实现action方法。
GenericAPIView用起来也不是非常方便,下面是一个例子:
# views.py
class BookGenericViewSet(GenericViewSet):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
pagination_class = PageNum
lookup_field = 'id'
lookup_url_kwarg = 'id'
def list(self, request):
res = self.paginate_queryset(self.get_serializer(self.get_queryset(), many=True).data)
return Response(res)
def retrieve(self, request, id):
user = get_object_or_404(self.get_queryset(), id=id)
ser = self.get_serializer(user)
return Response(ser.data)
# urls.py
urlpatterns = [
path('bookgeneric/', BookGenericViewSet.as_view({'get': 'list'})),
path('bookgeneric/<int:id>', BookGenericViewSet.as_view({'get': 'retrieve'})),
]ModelViewSet继承自GenericAPIVIew,ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。
ModelViewSet提供了list(),retrieve(),create(),update(),partial_update(),和destroy()方法。这对于简单的场景是非常实用的,我们可以只提供queryset,serializer_class,pagination_class等属性即可。同时DRF提供了适用于视图集的路由来方便使用。
ModelViewSet用起来就显得非常方便了,我们不需要实现各种方法了,只需要重写属性,然后配置路由即可。下面是一个例子:
# views.py
class BookModelViewSet(ModelViewSet):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
pagination_class = PageNum
lookup_field = 'id'
lookup_url_kwarg = 'id'
# urls.py
urlpatterns = [
path('bookmodelset/', BookModelViewSet.as_view({'get': 'list', 'post': 'create'})), # 创建和列表路由
path('bookmodelset/<int:id>', BookModelViewSet.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})), # 删改查路由
]只有在ModelViewSet这里,才能感到便捷和强大。但是目前的路由依旧不是让我们很满意。好在DRF提供了给视图集使用的路由方式。如下所示:
from rest_framework.routers import SimpleRouter
# 可以处理视图的路由器
router = SimpleRouter()
# 向路由器中注册视图集
router.register(r'drfbook', BookModelViewSet, basename='drfbook')
#追加路由
urlpatterns += router.urls使用DRF的路由,效果是一样的,如下所示:

