zoukankan      html  css  js  c++  java
  • day75

    视图家族

    1. views:视图类 - APIView,GenericAPIView(generics中)
    2. Mixins:视图工具类 - CreateModelMixin,ListModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin
    3. generics:工具视图类 - 九个类
    4. viewsets:视图集 - 两个视图集基类,两个视图集子类,一个工具类

    GenericAPIView类:

    拥有APIView的所有(1、拥有View的所有 2、重写as_view 3、重写dispatch 4、一系列类属性)

    queryset = models.Car.objects.filter(is_delete=False).all()
    不能直接写到objects结束,因为objects结束时,不是QuerySet对象,而是Manager对象,但`.all()`和`filter()`后一定是QuerySet对象
    

    Mixins视图工具类

    单查:

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

    单增:

    def post(self, request, *args, **kwargs):
    	return self.create(request, *args, **kwargs)
    

    群增:

    def get(self, request, *args, **kwargs):
    	return self.list(request, *args, **kwargs)
    

    Geneics工具视图类

    单独完成单查接口

    from rest_framework.generics import RetrieveAPIView
    class CarRetrieveAPIView(RetrieveAPIView):
        queryset = models.Car.objects.filter(is_delete=False).all()
        serializer_class = serializers.CarModelSerializer
        lookup_url_kwarg = 'pk'
    

    单独完成群查接口

    from rest_framework.generics import ListAPIView
    class CarListAPIView(ListAPIView):
        queryset = models.Car.objects.filter(is_delete=False).all()
        serializer_class = serializers.CarModelSerializer
    

    单查(get)、单整体改(put)、单局部改(patch)、单删接口(delete)

    from rest_framework.generics import RetrieveUpdateDestroyAPIView
    class CarRetrieveUpdateDestroyAPIView(RetrieveUpdateDestroyAPIView):
        queryset = models.Car.objects.filter(is_delete=False).all()
        serializer_class = serializers.CarModelSerializer
    

    APIView

    1. 拥有View的所有
    2. 重写as_view
    3. 重写dispatch
    4. 一系列类属性

    GenericAPIView基类

    • GenericAPIView是继承APIView的,使用完全兼容APIView
    • 重点:GenericAPIView在APIView基础上完成了哪些事
    1. get_queryset()方法:从queryset中获得model的queryset数据
    2. get_object()方法:在第一步的基础上,再通过有名分组pk确定唯一操作对象
    3. get_serializer()方法:从类属性serializer_class中获得serializer的序列化类

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

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

    代码:

    视图集:
    from rest_framework.viewsets import ViewSetMixin, GenericViewSet, ViewSet, ModelViewSet
    class CarReadOnlyAPIView(RetrieveModelMixin, ListModelMixin, GenericViewSet):
        queryset = models.Car.objects.filter(is_delete=False).all()
        serializer_class = serializers.CarModelSerializer
    

    六大接口:

    class CarModelViewSet(ModelViewSet):
        queryset = models.Car.objects.filter(is_delete=False).all()
        serializer_class = serializers.CarModelSerializer
    

    分析:从实际开发角度分析不合理点

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

    解决1:

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

    def many_update(self, request, *args, **kwargs):
        return APIResponse(msg='')
    def many_partial_update(self, request, *args, **kwargs):
        return APIResponse(msg='')
    def many_destroy(self, request, *args, **kwargs):
        return APIResponse(msg='')
    

    群增与单增必须公用一个接口,都要走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)
    

    mixins视图工具类们:- 辅助GeneriAPIView

    • Mixins有五个工具类文件(上面总结到),六个工具方法:单查(retrieve)、群查(list)、单增(create)、单删(destroy)、单整体改(update)、单局部改(partial_update)
    • 继承工具类可以简化请求函数的实现体,但是必须继承GenericAPIView,需要GenericAPIView类提供的几个类属性和方法(见上方GenericAPIView基类知识点)
    • 工具类的工具方法返回值都是Response类型对象,如果要格式化数据格式再返回给前台,可以通过 response.data 拿到工具方法返回的Response类型对象的响应数据

    原因:六个方法的实现体,调用的方法就是GenericAPIView提供的,所以要配合GenericAPIView类使用

    generics工具视图类们:九种组合

    1. 帮我们将不同个数不同种类的mixins与GenericAPIView进行组合
    2. 不同的组合帮我们实现好对应的get、post、put、patch、delete方法
    3. 需要我们自己配置三个类属性即可:queryset、serializer_class、lookup_url_kwarg

    代码:

    class CarView(APIView):
    	def get(self):
    	   obj,
            ser,
            response,
         
         
    class CarView(GenericAPIView):		#不会出现,中间产物
    	queryset,
    	serializer_class,
    	look_url_kwargs,
    	def get(self):
    	   obj,
            ser,
            response,
    
    
    class CarView(RetrieveModelMixin,GenericAPIView):	 #自定义组合,可以超过九种
    	queryset,
    	serializer_class,
    	look_url_kwargs,
    	def get(self):
    		self.retrieve()
    
    
    class CarView(RetrieveModelMixin):		#最终产物,系统提供了九种组合,RetrieveModelMixin是其中一种
    	queryset,
    	serializer_class,
    	look_url_kwargs,
    
    from rest_framework.viewsets import ModelViewSet
    class BookModelViewSet(ModelViewSet):
        queryset = models.Book.objects.filter(is_delete=False)
        serializer_class = serializers.BookModelSerializer
    
        # 删不是数据库,而是该记录中的删除字段
        def destroy(self, request, *args, **kwargs):
            instance = self.get_object()  # type: models.Book
            if not instance:
                return APIResponse(1, '删除失败')  # 实际操作,在此之前就做了判断
            instance.is_delete = True
            instance.save()
            return APIResponse(0, '删除成功')
    

    注:删不是数据库数据,而是删除记录中的字段

    视图集

    1、视图集都是优先继承ViewSetMixin类,再继承一个视图类(GenericAPIView或APIView)
           GenericViewSet、ViewSet
    
    2、ViewSetMixin提供了重写的as_view()方法,继承视图集的视图类,配置路由时调用as_view()必须传入 请求名-函数名 映射关系字典
          eg: url(r'^v5/books/$', views.BookGenericViewSet.as_view({'get': 'my_get_list'})),
          表示get请求会交给my_get_list视图函数处理
    
    from rest_framework.viewsets import ViewSetMixin, GenericViewSet, ViewSet, ModelViewSet
    class CarReadOnlyAPIView(RetrieveModelMixin, ListModelMixin, GenericViewSet):
        queryset = models.Car.objects.filter(is_delete=False).all()
        serializer_class = serializers.CarModelSerializer
    

    GenericAPIView 与 APIView 最为两大继承视图的区别

    1)GenericViewSet和ViewSet都继承了ViewSetMixin,as_view都可以配置 请求-函数 映射
    2)GenericViewSet继承的是GenericAPIView视图类,用来完成标准的 model 类操作接口
    3)ViewSet继承的是APIView视图类,用来完成不需要 model 类参与,或是非标准的 model 类操作接口
        post请求在标准的 model 类操作下就是新增接口,登陆的post不满足
        post请求验证码的接口,不需要 model 类的参与
    案例:登陆的post请求,并不是完成数据的新增,只是用post提交数据,得到的结果也不是登陆的用户信息,而是登陆的认证信息
    

    视图集总结:

    核心:视图集都继承了ViewSetMixin类,该类重写了as_view方法,相比APIView的as_view方法,额外多出了一个参数actions

    as_view({ ' get ' : ' list ' })传入的({ ' get ' : ' list ' })就被actions

    路由层(了解)

    from django.conf.urls import include
    from rest_framework.routers import SimpleRouter
    router = SimpleRouter()
    # 所有路由与ViewSet视图类的都可以注册,会产生 '^v6/cars/$' 和 '^v6/cars/(?P<pk>[^/.]+)/$'
    router.register('v6/cars', views.CarModelViewSet, basename='car')
    
    
    urlpatterns = [
        # 第一种添加子列表方式
        url(r'^', include(router.urls)),
    ]
    
    # 第二种添加子列表方式
    # urlpatterns.extend(router.urls)
    
    urlpatterns = [
        # 基础
        url(r'^v1/cars/$', views.CarAPIView.as_view()),
        # url(r'^v1/cars/(?P<pk>d+)/$', views.CarAPIView.as_view()),
    
        # Generic
        url(r'^v2/cars/$', views.CarGenericAPIView.as_view()),
        url(r'^v2/cars/(?P<pk>d+)/$', views.CarGenericAPIView.as_view()),
    
        # Generic过渡
        url(r'^v3/cars/$', views.CarReadCreateGenericAPIView.as_view()),
        url(r'^v3/cars/(?P<pk>d+)/$', views.CarReadCreateGenericAPIView.as_view()),
    
        # 工具视图类
        url(r'^v4/cars/$', views.CarListAPIView.as_view()),
        # url(r'^v4/cars/(?P<pk>d+)/$', views.CarListAPIView.as_view()),
    
        url(r'^v5/cars/$', views.CarRetrieveUpdateDestroyAPIView.as_view()),
        url(r'^v5/cars/(?P<pk>d+)/$', views.CarRetrieveUpdateDestroyAPIView.as_view()),
    
        # 视图集
        url(r'^v6/cars/$', views.CarReadOnlyAPIView.as_view({'get': 'list'})),
        url(r'^v6/cars/(?P<pk>d+)/$', views.CarReadOnlyAPIView.as_view({'get': 'retrieve'})),
    
        # url(r'^v7/cars/$', views.CarModelViewSet.as_view({
        #     'get': 'list',
        #     'post': 'create',
        #     'put': 'many_update',
        #     'patch': 'many_partial_update',
        #     'delete': 'many_destroy',
        # })),
        # url(r'^v7/cars/(?P<pk>d+)/$', views.CarModelViewSet.as_view({
        #     'get': 'retrieve',
        #     'put': 'update',
        #     'patch': 'partial_update',
        #     'delete': 'destroy',
        # })),
            # 第一种添加子列表方式
        url(r'', include(router.urls))
    ]
    # 第二种添加子列表方式
    # urlpatterns.extend(router.urls)
    
    
  • 相关阅读:
    171 01 Android 零基础入门 03 Java常用工具类02 Java包装类 01 包装类简介 01 Java包装类内容简介
    170 01 Android 零基础入门 03 Java常用工具类01 Java异常 08 Java异常总结 01 异常总结
    169 01 Android 零基础入门 03 Java常用工具类01 Java异常 07 异常链 01 异常链简介
    168 01 Android 零基础入门 03 Java常用工具类01 Java异常 06 自定义异常 01 自定义异常类
    167 01 Android 零基础入门 03 Java常用工具类01 Java异常 05 使用throw和throws实现异常处理 02 使用throw抛出异常对象
    166 01 Android 零基础入门 03 Java常用工具类01 Java异常 05 使用throw和throws实现异常处理 01 使用throws声明异常类型
    165 01 Android 零基础入门 03 Java常用工具类01 Java异常 04 使用try…catch…finally实现异常处理 05 return关键字在异常处理中的使用
    DevExpress WPF v20.2版本亮点放送:全新升级的PDF Viewer
    界面控件DevExpress使用教程:Dashboard – 自定义导出
    DevExpress WinForms帮助文档:表单控件
  • 原文地址:https://www.cnblogs.com/gfhh/p/12122075.html
Copyright © 2011-2022 走看看