zoukankan      html  css  js  c++  java
  • DRF 视图家族及路由层补充

    视图家族

    一、views视图类

    1、APIView类

    功能:

    1. 拥有view的所有属性和方法;
    2. 重写as_view,禁用csrf;
    3. 重写dispatch,分发任务,五大模块对数据进行二次封装;
    4. 设定了一系列类属性。

    2、GenericAPIView类(generics中)

    特点:

    1. 继承APIView,所以拥有APIView的所有属性和方法;
    2. get_queryset方法,配置queryset类属性,提供视图类相关的Models;
    3. 在第二条的基础上,get_object方法,配置look_url_kwarg类属性,提供视图类的具体Model;
    4. get_serializer方法,配置serializer_class类属性,提供视图类相关的序列化对象。

    分析:

    class GenericAPIView(views.APIView):
    
        def get_queryset(self):
        	获取自定义类中设定的queryset对象。
            
        def get_serializer(self):
            调用get_serializer_class方法;
            获取自定义类中设定的serializer_class序列化类
            
        def get_object(self):
            首先通过get_queryset获取自定义类中给定的queryset对象;
            然后获取自定义类中设定的lookup_url_kwarg过滤参数;
            如果没有就使用默认的 lookup_field='pk' 过滤参数;
            使用过滤参数对queryset对象进行过滤;
           	
        
        因此,在继承GenericAPIView来自定义类时,需要定义queryset、serializer_class及lookup_url_kwarg(非必要)
    

    目的:

    视图中的增删改查逻辑相似,但操作的资源不一致,操作资源包括:[操作单个资源对象]、[操作多个资源对象]以及[资源相关的序列化类],将这三者形成配置,那操作逻辑就一致,就可以进行封装。

    总结:

    GenericAPIView就是在APIView基础上额外提供了三个方法,三个类属性,如果不配合视图工具类,体现不出优势。

    二、mixins类:视图辅助工具

    特点:

    1. 需要配合GenericAPIView类使用;
    2. 将单查、群查、单增、群增、单整体改,单局部改所对应的六个接口写成retrieve、list、create、update、partial_update、destroy六个方法,封装到五个类中;
    3. 以上六个方法中需要用到GenericAPIView提供的三大方法,因此需要GenericAPIView类的配合;
    4. 默认返回的只有序列化后的对象包含的内容。

    1、RetrieveModelMixin

    单查

    class RetrieveModelMixin:
        def retrieve(self, request, *args, **kwargs):
        	实现单查。
        
        如果可以检索对象,则返回 200 OK 响应;
        将该对象的序列化表示作为响应的主体。
        
        否则将返回 404 Not Found。
    

    2、ListModelMixin

    群查

    class ListModelMixin:
        def list(self, request, *args, **kwargs):
            实现群查;
        
        如果查询集被填充了数据,则返回 200 OK 响应;
        将查询集的序列化表示作为响应的主体。
        相应数据可以任意分页。
    

    3、CreateModelMixin

    单增

    class CreateModelMixin:
        def create(self, request, *args, **kwargs):
        	实现单增。
        
        如果创建了一个对象,将返回一个 201 Created 响应;
        将该对象的序列化表示作为响应的主体。
        
        如果为创建对象提供的请求数据无效,将返回 400 Bad Request;
        其中错误详细信息作为响应的正文。
    

    4、UpdateModelMixin

    单整体改和单局部改

    class UpdateModelMixin:
        def update(self, request, *args, **kwargs):
            完成单整体改;
    
        def partial_update(self, request, *args, **kwargs):
            完成单局部改;
            
        如果更新成功,将返回一个 200 OK 响应;
        将对象的序列化表示作为响应的主体。
    
    	如果更新失败,将返回一个 400 Bad Request 响应;
        错误详细信息作为响应的正文。
    

    5、DestroyModelMixin

    单删

    class DestroyModelMixin:
        def destroy(self, request, *args, **kwargs):
            完成单删;
        如果删除对象,则返回 204 No Content 响应;
        否则返回 404 Not Found。
    

    三、generics类:包含辅助工具的通用视图类

    九个通用视图。

    这通常是你真正用到的那些,除非你需要深度定制的行为。

    这些视图类可以从 rest_framework.generics导入。

    class RetrieveAPIView(mixins.RetrieveModelMixin,
                          GenericAPIView):
        完成单查
        def get(self, request, *args, **kwargs):
            return self.retrieve(request, *args, **kwargs)
        
    
    class ListAPIView(mixins.ListModelMixin,
                      GenericAPIView):
        完成群查
        def get(self, request, *args, **kwargs):
            return self.list(request, *args, **kwargs)
        
        
        
    class CreateAPIView(mixins.CreateModelMixin,
                        GenericAPIView):
        完成单增
        def post(self, request, *args, **kwargs):
            return self.create(request, *args, **kwargs)
        
        
    class UpdateAPIView(mixins.UpdateModelMixin,
                        GenericAPIView):
        单整体改
        def put(self, request, *args, **kwargs):
            return self.update(request, *args, **kwargs)
        
        单局部改
        def patch(self, request, *args, **kwargs):
            return self.partial_update(request, *args, **kwargs)
    
    
    class DestroyAPIView(mixins.DestroyModelMixin,
                         GenericAPIView):
        完成单删
        def delete(self, request, *args, **kwargs):
            return self.destroy(request, *args, **kwargs)
    
    
    class ListCreateAPIView(mixins.ListModelMixin,
                            mixins.CreateModelMixin,
                            GenericAPIView):
        群查
        def get(self, request, *args, **kwargs):
            return self.list(request, *args, **kwargs)
        单增
        def post(self, request, *args, **kwargs):
            return self.create(request, *args, **kwargs)
    
    
    
        
    class RetrieveUpdateAPIView(mixins.RetrieveModelMixin,
                                mixins.UpdateModelMixin,
                                GenericAPIView):    
        单查
        def get(self, request, *args, **kwargs):
            return self.retrieve(request, *args, **kwargs)
        单整体改
        def put(self, request, *args, **kwargs):
            return self.update(request, *args, **kwargs)
        单局部改
        def patch(self, request, *args, **kwargs):
            return self.partial_update(request, *args, **kwargs)
    
    
    class RetrieveDestroyAPIView(mixins.RetrieveModelMixin,
                                 mixins.DestroyModelMixin,
                                 GenericAPIView):
        单查
        def get(self, request, *args, **kwargs):
            return self.retrieve(request, *args, **kwargs)
        单删
        def delete(self, request, *args, **kwargs):
            return self.destroy(request, *args, **kwargs)
    
    
    class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,
                                       mixins.UpdateModelMixin,
                                       mixins.DestroyModelMixin,
                                       GenericAPIView):
        单查
        def get(self, request, *args, **kwargs):
            return self.retrieve(request, *args, **kwargs)
        单整体改
        def put(self, request, *args, **kwargs):
            return self.update(request, *args, **kwargs)
        单局部改
        def patch(self, request, *args, **kwargs):
            return self.partial_update(request, *args, **kwargs)
        单删
        def delete(self, request, *args, **kwargs):
            return self.destroy(request, *args, **kwargs)
    
    
    

    四、viewsets视图集

    包含:

    一个工具类、两个视图集基类、两个视图集子类

    1、作用

    其中一个工具类重写了as_view方法,将自己定义的群查和单查方法的函数地址赋给get方法,这样就可以在路由来调用时,主动识别调用单查还是群查。

    2、如何使用

    路由中:as_view({'get':'list'}) 传入的{'get':'list'}就被actions接收,原理是将get请求映射给视图类的list函数进行处理。

    class ViewSetMixin:
    	视图集都继承了ViewSetMixin类,该类重写了as_view方法,相比APIView的as_view方法,额外多出了一个参数:actions。
        
        @classonlymethod
        def as_view(cls, actions=None, **initkwargs):
    
    
    
    class ViewSet(ViewSetMixin, views.APIView):
    
        pass
    
    
    class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
    
        pass
    
    
    class ReadOnlyModelViewSet(mixins.RetrieveModelMixin,
                               mixins.ListModelMixin,
                               GenericViewSet):
    
        pass
    
    
    class ModelViewSet(mixins.CreateModelMixin,
                       mixins.RetrieveModelMixin,
                       mixins.UpdateModelMixin,
                       mixins.DestroyModelMixin,
                       mixins.ListModelMixin,
                       GenericViewSet):
    
        pass
    
    
    1. GenericViewSet和ViewSet两个基类有什么区别:
      • GenericViewSet(ViewSetMixin,GenericAPIView):该分支严格满足资源接口
      • ViewSet(ViewSetMixin,APIView):该分支满足的接口与资源Model类关系不是特别密切(登录接口、短信验证码接口)
    2. ReadOnlyModelViewSet,ModelViewSet两个视图集子类,就是做个一堆mixin与GenericViewSet相结合,自己在urls文件中配置as_view的action分发。

    3、ModelViewSet的不合理之处及解决方法

    不合理之处:

    1. 没有群增,群整体改,群局部改,群删四个接口
    2. 删除操作视图集默认走的destroy方法是将资源从数据库中删除,通常一个做字段is_delete字段修改表示删除
    3. 响应的结果只有数据,没有数据状态码和状态信息

    解决方法:

    1. 群整体改,群局部改,全删三个接口可以独立成三个方法

      def many_update(self, request, *args, **kwargs):
          pass
      def many_partial_update(self, request, *args, **kwargs):
          pass
      def many_destroy(self, request, *args, **kwargs):
          pass
      
      • 群增与单增必须公用一个接口,都要走create方法 - 重写create方法,用逻辑进行拆分
      def create(self, request, *args, **kwargs):
          request_data = request.data
          if isinstance(request_data, list):
              car_ser = self.get_serializer(data=request_data, many=True)
              car_ser.is_valid(raise_exception=True)
              car_obj = car_ser.save()
              return APIResponse(msg='群增成功', results=self.get_serializer(car_obj, many=True).data)
      
          return super().create(request, *args, **kwargs)
      
    2. destroy方法是完成is_delete字段值修改 - 重写destroy方法,自定义实现体

      def destroy(self, request, *args, **kwargs):
          car_obj = self.get_object()
          car_obj.is_delete = True
          car_obj.save()
          return APIResponse(msg='删除成功')
      
    3. 让群查有状态码和状态信息 - 重写list方法

      def list(self, request, *args, **kwargs):
          response = super().list(request, *args, **kwargs)
          return APIResponse(results=response.data)
      

    路由层补充

    路由的其他写法:SimpleRouter

    会遇到,看到了要认识:

    # urls.py
    from rest_framework.routers import SimpleRouter
    router = SimpleRouter()
    router.register('v2/cars', views.CarModelViewSet, basename='car')
    
    urlpatterns = [
        url(r'^v1/cars/$', views.CarAPIView.as_view()),
    
        url(r'', include(router.urls))
    ]
    /
    urlpatterns += router.urls
    /
    urlpatterns = router.urls
    
  • 相关阅读:
    PHP_Code_challenge(代码审计)
    超全局变量$GLOBALS
    upload-labs(文件上传)
    CTF bugku 论剑场 web20
    多次Printf()是否使用用同一栈帧的参数?
    (转载于度盘)小迪安全渗透-学习讲义
    SQL数据库操作练习(2)
    .htaccess绕过
    PHP序列化思考(9.14已修改)
    SQL数据库操作练习(1)
  • 原文地址:https://www.cnblogs.com/bowendown/p/12121962.html
Copyright © 2011-2022 走看看