zoukankan      html  css  js  c++  java
  • 19-视图集ViewSet和路由Routers

    一、视图集ViewSet

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

    1、list()提供一组数据

    2、retrieve()提供单个数据

    3、create()创建数据

    4、update()保存数据

    5、destrory()删除数据

    ViewSet视图集不在实现get()、post()等方法,而是实现动作actionlist()create()等。视图集只在使用as_view()方法的时候,才会将action动作与具体请求方式对应上。如:

    class BookInfoViewSet(viewsets.ViewSet):
    
        def list(self, request):
            books = BookInfo.objects.all()
            serializer = BookInfoSerializer(books, many=True)
            return Response(serializer.data)
    
        def retrieve(self, request, pk=None):
            try:
                books = BookInfo.objects.get(id=pk)
            except BookInfo.DoesNotExist:
                return Response(status=status.HTTP_404_NOT_FOUND)
            serializer = BookInfoSerializer(books)
            return Response(serializer.data)

    设置路由如下:

    urlpatterns = [
        path('books/', BookInfoViewSet.as_view({'get':'list'}),
        re_path('books/(?P<pk>d+)/', BookInfoViewSet.as_view({'get': 'retrieve'})
    ]

    1、常用视图集父类

      1、ViewSet

      继承自APIViewViewSetMixin,作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等。ViewSet主要通过继承ViewSetMixin来实现在调用as_view()时传入字典(如{'get':'list'})的映射处理工作。在ViewSet中,没有提供任何动作action方法,需要我们自己实现action方法。

      2、GenericViewSet

      使用ViewSet通常并不方便,因为list、retrieve、create、update、destory等方法都需要自己编写,而这些方法与前面讲过的Mixin扩展类提供的方法同名,所以我们可以通过继承Mixin扩展类来复用这些方法而无需自己编写。但是Mixin扩展类依赖与GenericAPIView,所以还需要继承GenericAPIViewGenericViewSet就帮助我们完成了这样的继承工作,继承自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 BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
        queryset = BookInfo.objects.all()
        serializer_class = BookInfoSerializer

    路由设置:

    urlpatterns = [
        path('books/', views.BookInfoViewSet.as_view({'get': 'list'})),
        re_path('books/(?P<pk>d+)/', views.BookInfoViewSet.as_view({'get': 'retrieve'})),
    ]

      3、ModelViewSet

      继承自GenericViewSet,同时包括了ListModelMixinRetrieveModelMixinCreateModelMixinUpdateModelMixinDestoryModelMixin

      4、ReadOnlyModelViewSet

      继承自GenericViewSet,同时包括了ListModelMixinRetrieveModelMixin

    2、视图集中定义附加action动作

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

    from rest_framework import mixins
    from rest_framework.viewsets import GenericViewSet
    from rest_framework.decorators import action
    
    class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
        queryset = BookInfo.objects.all()
        serializer_class = BookInfoSerializer
    
        def latest(self, request):
            """
            返回最新的图书信息
            """
            book = BookInfo.objects.latest('id')
            serializer = self.get_serializer(book)
            return Response(serializer.data)
    
        def read(self, request, pk):
            """
            修改图书的阅读量数据
            """
            book = self.get_object()
            book.bread = request.data.get('read')
            book.save()
            serializer = self.get_serializer(book)
            return Response(serializer.data)
    自定义动作

    路由定义:

    urlpatterns = [
        path('books/', views.BookInfoViewSet.as_view({'get': 'list'})),
        path('books/latest/', views.BookInfoViewSet.as_view({'get': 'latest'})),
        re_path('books/(?P<pk>d+)/', views.BookInfoViewSet.as_view({'get': 'retrieve'})),
        re_path('books/(?P<pk>d+)/read/', views.BookInfoViewSet.as_view({'put': 'read'})),
    ]

    3、action属性

      在视图集中,我们可以通过action对象属性来获取当前请求视图集时的action动作是哪个。

    例如:

    def get_serializer_class(self):
        if self.action == 'create':
            return OrderCommitSerializer
        else:
            return OrderDataSerializer

    4、视图集的继承关系

    二、 路由Routers

      对于视图集ViewSet,我们除了可以自己手动指明请求方式与动作action之间的对应关系外,还可以使用Routers来帮助我们快速实现路由信息。REST framework提供了两个router

    • SimpleRouter
    • DefaultRouter

    1、使用方法

      1、创建router对象,并注册视图集,例如:

    from rest_framework import routers
    
    router = routers.SimpleRouter()
    router.register(r'books', BookInfoViewSet, base_name='book')
    register(prefix, viewset, base_name)
    
    prefix 该视图集的路由前缀
    viewset 视图集
    base_name 路由名称的前缀

    上面的代码会形成路由如下:

    ^books/$    name: book-list
    ^books/{pk}/$   name: book-detail

    2、添加路由数据(两种方式)

    urlpatterns = [
        ...
    ]
    urlpatterns += router.urls

    或者是:

    urlpatterns = [
        ...
        re_path('^', include(router.urls))
    ]

    2、视图集中附加action的声明

      在视图集中,如果想要让Router自动帮助我们为自定义的动作生成路由信息,需要使用rest_framework.decorators.action装饰器。以action装饰器装饰的方法名会作为action动作名,与listretrieve等同。action装饰器可以接收两个参数:

    • methods: 声明该action对应的请求方式,列表传递
    • detail: 声明该action的路径是否与单一资源对应,及是否是xxx/<pk>/action方法名/
      • True 表示路径格式是xxx/<pk>/action方法名/
      • False 表示路径格式是xxx/action方法名/

    举例:

    from rest_framework import mixins
    from rest_framework.viewsets import GenericViewSet
    from rest_framework.decorators import action
    
    class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
        queryset = BookInfo.objects.all()
        serializer_class = BookInfoSerializer
    
        # detail为False 表示路径名格式应该为 books/latest/
        @action(methods=['get'], detail=False)
        def latest(self, request):
            """
            返回最新的图书信息
            """
            ...
    
        # detail为True,表示路径名格式应该为 books/{pk}/read/
        @action(methods=['put'], detail=True)
        def read(self, request, pk):
            """
            修改图书的阅读量数据
            """
            

    由路由器自动为此视图集自定义action方法形成的路由会是如下内容:

    ^books/latest/$    name: book-latest
    ^books/{pk}/read/$  name: book-read

    3、路由router形成URL的方式

      1、 SimpleRouter

       2、DefaultRouter

     DefaultRouterSimpleRouter的区别是,DefaultRouter会多附带一个默认的API根视图,返回一个包含所有列表视图的超链接响应数据。

  • 相关阅读:
    使用C++为对象分配与释放内存时的几个好习惯
    OGRE渲染流程
    【问题解决记录】无法识别的标志“-sdlMode”,在“p2”中
    四元数 Quaternion
    《The Cg Tutorial》阅读笔记——凹凸贴图 Bump Mapping
    尝试优化骨骼动画计算的意外收获——使用嵌入式汇编对float转int进行优化
    Model 的 Meta 选项
    dns资料
    ansible中的变量
    DockerFile与docker-compose.yml是什么
  • 原文地址:https://www.cnblogs.com/lishuntao/p/11737017.html
Copyright © 2011-2022 走看看