zoukankan      html  css  js  c++  java
  • drf之视图集

    一、为什么要有视图集

    ​ 我们使用drf提供的generics包可以很轻松的实现六大基础接口,但我们会发现群查和单查却无法共存。这是由于我们寄希望于继承generics.ListAPIView来实现群查,同时有希望继承generics.RetrieveAPIView来实现单查,但由于继承顺序的关系,群查和单查并不能共存。

    我们希望在访问 群查或单查的接口时,可以有另外一种映射关系。

    """ ViewSetMixin类存在理由推到
    1)工具视图类,可以完成应付六大基础接口,唯一缺点是单查与群查接口无法共存
    	(只配置queryset、serializer_class、lookup_field)
    2)不能共存的原因:RetrieveAPIView和ListAPIView都是get方法,不管带不带pk的get请求,只能映射给一个get方法
    3)能不能修改映射关系:
    	比如将/books/的get请求映射给list方法,
    	将/books/(pk)/的get请求映射给retrieve方法,
    	甚至可以随意自定义映射关系
    """
    

    二、视图集

    ViewSetMixin类是视图集的基类。它重写了as_view方法,rest_framework.viewsets下的类都间接或直接的继承了它,所以都会继承它的方法。

    源码分析
    def as_view(cls, actions=None, **initkwargs):
    	'''.......'''
        # 必须提供actions
        if not actions:
            raise TypeError('....')
            
    	'''........'''
        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            self.action_map = actions
            # {'get':'list'}获取请求方式method--->映射方法list
            for method, action in actions.items():
                handler = getattr(self, action)
                # 修改了映射get-->list
                setattr(self, method, handler)
    
            if hasattr(self, 'get') and not hasattr(self, 'head'):
                self.head = self.get
    
            self.request = request
            self.args = args
            self.kwargs = kwargs
    
            # 还是由dispatch进行分发
            return self.dispatch(request, *args, **kwargs)
        view.cls = cls
        view.initkwargs = initkwargs
        view.actions = actions
        return csrf_exempt(view)
    
    urls.py

    我们看urls.py中的变化再看as_view的源码,两条url的as_view的actions参数是不一样的。

    # 群查接口的as_view的actions
    url(r'^v3/books/$', views.BookV3APIView.as_view(
        {'get': 'list', 'post': 'create'}
    	)),
    
    # 单查接口的as_view的actions
    url(r'^v3/books/(?P<pk>d+)/$', views.BookV3APIView.as_view(
            {'get': 'retrieve', 'put': 'update', 'patch': 'partial_update', 'delete': 'destroy'}
        )),
    
    views.py
    from rest_framework.viewsets import ModelViewSet
    from rest_framework.response import Response
    class BookV3APIView(ModelViewSet):
        queryset = models.Book.objects.filter(is_delete=False).all()
        serializer_class = serializers.BookModelSerializer
    

    可以在ModelViewSet的源码中看到继承了一系列generic包下的一系列类。我们可以借用它直接完成六大接口!

    三、路由组件

    可以看到as_view中自己配置的actions的对应关系也比较繁琐,drf还为我们提供了路由组件,来配合视图集使用(路由组件不能单独存在,必须配合视图集使用)

    urls.py
    from django.conf.urls import url, include
    from . import views
    # 路由组件,必须配合视图集使用
    from rest_framework.routers import SimpleRouter
    router = SimpleRouter()
    
    # 以后就写视图集的注册即可:BookV3APIView和BookV4APIView都是视图集
    router.register('v3/books', views.BookV3APIView, 'book')
    router.register('v4/books', views.BookV4APIView, 'book')
    
    urlpatterns = [
        url('', include(router.urls))
    ]
    
    views.py
    from rest_framework.viewsets import ReadOnlyModelViewSet
    class BookV4APIView(ReadOnlyModelViewSet):
        queryset = models.Book.objects.filter(is_delete=False).all()
        serializer_class = serializers.BookModelSerializer
    

    四、自定义路由组件

    router.py
    from rest_framework.routers import SimpleRouter as DrfSimpleRouter
    from rest_framework.routers import Route, DynamicRoute
    
    class SimpleRouter(DrfSimpleRouter):
        routes = [
            # List route.
            Route(
                url=r'^{prefix}{trailing_slash}$',
                mapping={
                    'get': 'list',
                    'post': 'create',  # 注:群增只能自己在视图类中重写create方法,完成区分
                    'delete': 'multiple_destroy',  # 新增:群删
                    'put': 'multiple_update',  # 新增:群整体改
                    'patch': 'multiple_partial_update'  # 新增:群局部改
                },
                name='{basename}-list',
                detail=False,
                initkwargs={'suffix': 'List'}
            ),
            # Dynamically generated list routes. Generated using
            # @action(detail=False) decorator on methods of the viewset.
            DynamicRoute(
                url=r'^{prefix}/{url_path}{trailing_slash}$',
                name='{basename}-{url_name}',
                detail=False,
                initkwargs={}
            ),
            # Detail route.
            Route(
                url=r'^{prefix}/{lookup}{trailing_slash}$',
                mapping={
                    'get': 'retrieve',
                    'put': 'update',
                    'patch': 'partial_update',
                    'delete': 'destroy'
                },
                name='{basename}-detail',
                detail=True,
                initkwargs={'suffix': 'Instance'}
            ),
            # Dynamically generated detail routes. Generated using
            # @action(detail=True) decorator on methods of the viewset.
            DynamicRoute(
                url=r'^{prefix}/{lookup}/{url_path}{trailing_slash}$',
                name='{basename}-{url_name}',
                detail=True,
                initkwargs={}
            ),
        ]
    
  • 相关阅读:
    Pandas 数值计算和统计基础
    Pandas 基本技巧
    Pandas 索引和切片
    Pandas 数据结构Dataframe:基本概念及创建
    Pandas 数据结构Series:基本概念及创建
    Numpy 通用函数
    Numpy 随机数
    Numpy 索引及切片
    Numpy 练习题
    Python通过fork的方式防止僵尸进程
  • 原文地址:https://www.cnblogs.com/Ghostant/p/12363220.html
Copyright © 2011-2022 走看看