• drf(九)—视图


    drf(九)—视图

    说明:drf 的开发一般使用 CBV 进行开发,Django 的原生视图类是 View 类,drf 中使用较普通的是APIView

    1.GenericAPIView

    该类继承于APIView,只是封装了一些调用方法,完成我们的常用操作。

    使用方式

    class View1View(GenericAPIView):
        queryset = models.Role.objects
        serializer_class = RoleSerializers
        pagination_class = PageNumberPagination
    
        def get(self, request, *args, **kwargs):
            roles=self.get_queryset() # 获取到数据库中的数据
            pager_roles=self.paginate_queryset(roles)
            ser=self.get_serializer(instance=pager_roles,many=True)
            return Response(ser.data)
    

    使用 Pycharm 查看类的继承关系

    image-20220411090234548

    说明:本类使用较少不做过多解释。

    2.GenericViewSet

    class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
        """
        The GenericViewSet class does not provide any actions by default,
        but does include the base set of generic view behavior, such as
        the `get_object` and `get_queryset` methods.
        """
        pass
    
    

    ViewSetMixin 优先级高于后面的 GenericAPIView 类,多继承的顺序问题。

    因此我们也可以在自定义的视图中直接继承这两个类。

    image-20220411095442110

    class View2View(GenericViewSet):
    
        def get(self,rewuest,*args,**kwargs):
            return Response("....")
    

    image-20220411100633111

    函数as_view()报错,缺少参数,进行修改;

    此时,视图的不同已经开始影响了路由系统。

    re_path('^api/(?P<version>[v1|v2]+)/viewv2/',view.View2View.as_view({'get':'list'})),
    
    class View2View(GenericViewSet):
        def list(self,rewuest,*args,**kwargs):
            return Response("....")
    

    image-20220411100935373

    修改后并将该方法的名称映射为字典的值。

    进行源码剖析查看为何要这样传参。

    class ViewSetMixin:
        @classonlymethod
        def as_view(cls, actions=None, **initkwargs):
            cls.name = None
            cls.description = None
    
            cls.suffix = None
    
            cls.detail = None
    
            cls.basename = None
    
            if not actions:
                raise TypeError("The `actions` argument must be provided when "
                                "calling `.as_view()` on a ViewSet. For example "
                                "`.as_view({'get': 'list'})`")
    
            for key in initkwargs:
                if key in cls.http_method_names:
                    raise TypeError("You tried to pass in the %s method name as a "
                                    "keyword argument to %s(). Don't do that."
                                    % (key, cls.__name__))
                # 使用反射查看是否存在键,不存在则抛出异常
                if not hasattr(cls, key): 
                    raise TypeError("%s() received an invalid keyword %r" % (
                        cls.__name__, key))
            if 'name' in initkwargs and 'suffix' in initkwargs:
                raise TypeError("%s() received both `name` and `suffix`, which are "
                                "mutually exclusive arguments." % (cls.__name__))
    
            def view(request, *args, **kwargs):
                self = cls(**initkwargs)
                if 'get' in actions and 'head' not in actions:
                    actions['head'] = actions['get']
                self.action_map = actions
                for method, action in actions.items():
                    handler = getattr(self, action)
                    # 使用反射进行方法。
                    setattr(self, method, handler)
                self.request = request
                self.args = args
                self.kwargs = kwargs
                return self.dispatch(request, *args, **kwargs)
    
            update_wrapper(view, cls, updated=())
    
            update_wrapper(view, cls.dispatch, assigned=())
    
            view.cls = cls
            view.initkwargs = initkwargs
            view.actions = actions
            return csrf_exempt(view) # 使得函数通过CSRF_TOKEN
    

    3.ModelViewSet

    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
    

    列表类

    class ListModelMixin:
        """
        List a queryset.
        """
        def list(self, request, *args, **kwargs):
            queryset = self.filter_queryset(self.get_queryset())
    
            page = self.paginate_queryset(queryset)
            if page is not None:
                serializer = self.get_serializer(page, many=True)
                return self.get_paginated_response(serializer.data)
    
            serializer = self.get_serializer(queryset, many=True)
            return Response(serializer.data)
    # 改类帮我们写了list方法,我们不需要在进行编写
    

    其他的类相同。

    class View3View(ListModelMixin,GenericViewSet):# 只有查的功能
        queryset = models.Role.objects.all()
        serializer_class = RoleSerializers
        pagination_class = PageNumberPagination
    

    image-20220411134322275

    因此只要继承 ModelViewSet 可以直接获得增删改查的方法。

    传入需要更新的视图或者查询单条记录的时候使用路由进行传参

    image-20220411140121249

    总结

    1. 继承的越多,自己写的代码就越少;

    2. 影响路由系统,一个 url 会写两个路由;

    3. 使用建议

      1. 当对某张表需要具备增删改查的所有操作时使用 ModelViewSet,较好

      2. 当只实现某项功能的时候可以去单独执行某项 XXXModelMixin;

        总结:
        	a.增删改查   ModelViewSet
        	b.增删      CreateModelMixin,DestroyModelMixin  GenericViewSet
        	c.复杂逻辑   GenericViewSet 或 APIView 
        
      3. 当业务功能较为复杂的时候使用APIView

    补充:

    视图的完整继承类图

    viewsets

  • 相关阅读:
    借壳上市[来自百度]
    DIY协同办公平台(C/S)系列3之内部邮箱篇
    测试用例设计场景法
    客户关系管理系统提高企业对客户的响应速度
    CRM--销售管理的灵药
    CRM的两个问题
    需求分析是CRM系统实施的关键
    如何实施CRM客户关系管理系统
    CRM的三重境界
    企业需要更好的认识客户关系管理系统
  • 原文地址:https://www.cnblogs.com/Blogwj123/p/16129777.html
Copyright © 2020-2023  润新知