视图集ViewSet

视图集

使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中:

  • list() 提供一组数据

  • retrieve() 提供单个数据

  • create() 创建数据

  • update() 保存数据

  • destory() 删除数据

ViewSet视图集类不再实现get()、post()等方法,而是实现动作 action 如 list() 、create() 等。

使用django按照restful开发接口,一个实体类的借口至少需要做两个视图,因为django是按照请求名称小写后去映射处理的方法,导致无法放入一个视图中。

视图集只在使用as_view()方法的时候,才会将action动作与具体请求方式对应上。

class BookViewSet(viewsets.ViewSet):

    def list(self, request): # 获取所有图书
        books = Book.objects.all()
        serializer = BookSerializer(books, many=True)
        return Response(serializer.data)

    def retrieve(self, request, pk=None): # 获取指定某个图书
        try:
            books = Book.objects.get(id=pk)
        except Book.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)
        serializer = BookSerializer(books)
        return Response(serializer.data)

在设置路由时,可以如下操作:

urlpatterns = [
    url(r'^books/$', BookViewSet.as_view({'get':'list'}), # get方法映射list
    url(r'^books/(?P<pk>\d+)/$', BookViewSet.as_view({'get': 'retrieve'}) # get方法映射retrieve
]

使用ViewSet需要手动指定映射的方法,而且list、retrieve、create、update、destory等方法都需要自己编写。

常用的视图集类

ViewSet

继承自APIViewViewSetMixin,作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等。

ViewSet主要通过继承ViewSetMixin来实现在调用as_view()时传入字典(如{'get':'list'})的映射处理工作。

在ViewSet中,没有提供任何动作action方法,需要我们自己实现action方法。

class ViewSet(ViewSetMixin, views.APIView):
    """
    The base ViewSet class does not provide any actions by default.
    """
    pass

GenericViewSet

使用ViewSet通常并不方便,因为list、retrieve、create、update、destory等方法都需要自己编写,而这些方法与前面讲过的Mixin扩展类提供的方法同名,所以可以通过继承Mixin扩展类来复用这些方法而无需自己编写。但是Mixin扩展类依赖与GenericAPIView,所以还需要继承GenericAPIView

GenericViewSet就帮助我们完成了这样的继承工作,继承自GenericAPIViewViewSetMixin,在实现了调用as_view()时传入字典(如{'get':'list'})的映射处理工作的同时,还提供了GenericAPIView提供的基础方法,可以直接搭配Mixin扩展类使用。

例如:

from rest_framework import mixins
from rest_framework.viewsets import GenericViewSet
from rest_framework.decorators import action

class BookViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    # 无需手动再写list、retrieve方法,因为继承的ListModelMixin和RetrieveModelMixin已实现

url的定义:

urlpatterns = [
    url(r'^books/$', views.BookViewSet.as_view({'get': 'list'})),
    url(r'^books/(?P<pk>\d+)/$', views.BookViewSet.as_view({'get': 'retrieve'})),
]

ModelViewSet

继承自GenericViewSet,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。

class ModelViewSet(mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet):
    """
    A viewset that provides default `create()`, `retrieve()`, `update()`,
    `partial_update()`, `destroy()` and `list()` actions.
    """
    pass

ReadOnlyModelViewSet

继承RetrieveModelMixin、ListModelMixin、GenericViewSet

class ReadOnlyModelViewSet(mixins.RetrieveModelMixin,
                           mixins.ListModelMixin,
                           GenericViewSet):
    """
    A viewset that provides default `list()` and `retrieve()` actions.
    """
    pass

 

视图集中定义附加action动作

在视图集中,除了上述默认的方法动作外,还可以添加自定义动作。

from rest_framework import mixins
from rest_framework.viewsets import GenericViewSet
from rest_framework.decorators import action

class BookViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    def latest(self, request):
        """
        查询id最大的图书信息
        """
        book = Book.objects.latest('id')
        serializer = self.get_serializer(book)
        return Response(serializer.data)

    def price(self, request, pk):
        """
        只修改图书价格
        """
        book = self.get_object()
        book.price = request.data.get('price')
        book.save()
        serializer = self.get_serializer(book)
        return Response(serializer.data)

url的定义:

urlpatterns = [
    url(r'^books/$', views.BookViewSet.as_view({'get': 'list'})),
    url(r'^books/latest/$', views.BookViewSet.as_view({'get': 'latest'})),
    url(r'^books/(?P<pk>\d+)/$', views.BookViewSet.as_view({'get': 'retrieve'})),
    url(r'^books/(?P<pk>\d+)/price/$', views.BookViewSet.as_view({'put': 'price'})),
]

视图集继承关系

 

posted @ 2021-08-24 17:50  wang_longan  阅读(49)  评论(0编辑  收藏  举报