DRF(Django RestFramework)视图集总结

视图集

视图集有四个封装类,ViewSet基础封装、GenericViewSet进一步封装查询集和序列化器、ModelViewSet进一步封装action、ReadOnlyModelViewSet提取只读action。以下是展开介绍。

一、ViewSet

# 源码
class ViewSet(ViewSetMixin, views.APIView):
    pass

没错,源码中ViewSet就是只有继承而没有实现任何方法&定义任何属性,我们对APIView已经不陌生了,我上一篇DRF类视图中有,它主要实现请求,响应,验证,异常,限流等。主要看ViewSetMixin类。

class ViewSetMixin(object):
    """
    Overrides `.as_view()` so that it takes an `actions` keyword that performs
    the binding of HTTP methods to actions on the Resource.
    For example
    view = MyViewSet.as_view({'get': 'list', 'post': 'create'})
    重写了as_view方法,它需要执行一个`actions`关键字
     HTTP方法绑定到资源上的操作
    """
    def as_view(cls, actions=None, **initkwargs)
	    # 有兴趣可以具体看实现,这里就不复制了
	    pass 

由源码可以看出,仅仅提供了as_view方法将请求方法绑定到了actions关键字上,并没有给出actions的具体实现,所以我们在使用ViewSet的时候,需要自己定义出action方法(查询集和序列化器需要手动实例化调用、异常抛出等),然后通过as_view绑定请求方法即可。

# 举例1.1
# 继承视图集ViewSet
class BooksAPIViewSet(ViewSet):
    # 定义action中的list实现查询所有
    def list(self, request):
	    # 手动实现查询集
        books = BookInfo.books.all()
        # 手动使用序列化器
        serializer = BookInfoModelSerializer(books, many=True)
        # 返回响应,APIView中实现的Response响应对象
        return Response(serializer.data)

    # 定义action中的retrieve检索条件
    def retrieve(self, request, pk):
        try:
            book = BookInfo.books.get(id=pk)
        except BookInfo.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)
        serializer = BookInfoSerializer(book)
        return Response(serializer.data)

我们实现了视图集,为了使他生效,我们还需要指定他们的url。

# as_view中实现了get->list的绑定,是我们发送的get /books/请求能够生效
url(r'^books/$', views.BooksAPIViewSet.as_view({'get': 'list'})),
# 绑定get->retrieve,使得get /books/id/生效
url(r'^books/(?P\d+)/$', views.BooksAPIViewSet.as_view({'get': 'retrieve'})),

综上:继承ViewSet,需要自定义action,action中需要自己实现查询集和序列化器,url中as_view需要绑定方法和action的对应关系

二、GenericViewSet

# 源码
class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
    pass

同样GenericViewSet类中也没有任何实现,全部继承自ViewSetMixin和GenericAPIView。DRF类视图中有GenericAPIView的介绍,它主要实现指定查询集queryset/get_queryset/get_object和指定序列化器serializer_class/get_serializer_class等。ViewSetMixin类刚刚提过主要重写实现了as_view()用于request方法和action的绑定。注意:GenericViewSet一般需要和5种扩展类执行。

# 举例1.2
# 继承视图集GenericViewSet
class BooksAPIViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
    # 指定查询集和序列化器
    # 之所以不用定义get/post方法,是因为重写了as_view方法,将get映射为了list方法
    # 之所以不用第一action,是因为继承了ListModelMixin等扩展类
    queryset = BookInfo.books.all()
    serializer_class = BookInfoModelSerializer

三、ModelViewSet

# 源码
class ModelViewSet(mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet):
	 pass

同样,我们的ModelViewSet中也没有任何功能的具体实现,单纯的继承五个扩展类的功能和GenericViewSet的功能。很明显,五个扩展类主要实现了Create(增)List/Retrieve(查)Update(改)Destroy(删)。GenericViewSet主要实现了序列化器的指定,查询集的指定,和as_view的重写。

四、ReadOnlyModelViewSet

# 源码
class ReadOnlyModelViewSet(mixins.RetrieveModelMixin,
                           mixins.ListModelMixin,
                           GenericViewSet):
	pass

由此可以看出ReadOnlyModelViewSet仅仅是查询集。

你可能感兴趣的:(DRF,类视图集)