视图家族解析

视图家族解析

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

 1)GenericViewSet和ViewSet都继承了ViewSetMixin,as_view都可以配置 请求-函数 映射
    
 2)GenericViewSet继承的是GenericAPIView视图类,用来完成标准的 model 类操作接口

 3)ViewSet继承的是APIView视图类,用来完成不需要 model 类参与,或是非标准的 model 类操作接口
    
      post请求在标准的 model 类操作下就是新增接口,登陆的post不满足
      post请求验证码的接口,不需要 model 类的参与
    
 案例:登陆的post请求,并不是完成数据的新增,只是用post提交数据,得到的结果也不是登陆的用户信息,而是登陆的认证信息

删除操作:

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, '删除成功')

群删:

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='删除成功')

群增:

    群增与单增必须公用一个接口,都要走create方法 - 重写create方法,用逻辑进行拆分

class CarModelViewSet(ModelViewSet):
    queryset = models.Car.objects.filter(is_delete=False).all()
    serializer_class = serializers.CarModelSerializer
   
    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) 

路由添加子列表方式:

from django.conf.urls import include
from rest_framework.routers import SimpleRouter
router = SimpleRouter()

# 所有路由与ViewSet视图类的都可以注册,会产生 '^v6/books/$' 和 '^v6/books/(?P<pk>[^/.]+)/$'
router.register('v6/books', views.BookModelViewSet)

urlpatterns = [
    # 第一种添加子列表方式
    url(r'^', include(router.urls)),
]
    #第二种添加子列表方式
urlpatterns.extend(router.urls)

为响应信息添加状态码:

响应的结果只有数据,没有数据状态码和状态信息 ???

让群查有状态码和状态信息 - 重写list方法
    def list(self, request, *args, **kwargs):
        response = super().list(request, *args, **kwargs)
        return APIResponse(results=response.data)

mixins视图工具类:

from rest_framework.mixins import RetrieveModelMixin, ListModelMixin, CreateModelMixin

class CarReadCreateGenericAPIView(ListModelMixin, RetrieveModelMixin, CreateModelMixin, GenericAPIView):
    
    queryset = models.Car.objects.filter(is_delete=False).all()
    serializer_class = serializers.CarModelSerializer
    lookup_url_kwarg = 'pk'
    
     # 单查

    def get(self, request, *args, **kwargs):
        # car_obj = self.get_object()
        # car_ser = self.get_serializer(car_obj)
        # return APIResponse(results=car_ser.data)
        response = self.retrieve(request, *args, **kwargs)
        return APIResponse(results=response.data)


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

Generics工具视图类:

# 单独完成群查接口
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

推演过程:

class CarView(APIView):        # 初始版(全手撸)
    def get(self):
        obj,
        ser,
        response,
        
class CarView(GenericAPIView):  # 不会出现,中间产物
    queryset,
    serializer_class,
    lookup_url_kwarg,
    def get(self):
        obj,
        ser,
        response,

class CarView(RetrieveModelMixin, GenericAPIView):  # 自定义组合,可以超过九种
    queryset,
    serializer_class,
    lookup_url_kwarg,
    def get(self):
        self.retrieve()
        
class CarView(RetrieveAPIView):  # 最终产物,系统只提供了九种组合,RetrieveAPIView是其中一种
    queryset,
    serializer_class,
    lookup_url_kwarg,

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

总结:GenericAPIView就是在APIView基础上额外提供了三个方法,三个类属性,如果不配合视图工具类,体现不出优势
目的:视图中的增删改查逻辑相似,但操作的资源不一致,操作资源就是操作 资源对象们、资源对象以及资源相关的序列化类,
将这三者形成配置,那操作逻辑就一致,就可以进行封装

3、mixins视图工具类们:五个类,六个方法
1)要配合GenericAPIView类使用,将单查、群查、单增,单整体改,单局部改,单删六个接口
封装成retrieve、list、create、update、partial_update、destroy六个方法
原因:六个方法的实现体,调用的方法就是GenericAPIView提供的,所以要配合GenericAPIView类使用

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

视图集总结


    核心:视图集都继承了 ViewSetMixin类,该类重写了as_view方法,相比APIView的as_view方法,额外多出了一个参数actions
    
    as_view({'get': 'list'}) 传入的{'get': 'list'}就被actions介绍,原理是将get请求映射给视图类的list函数进行处理

1)为什么有GenericViewSet和ViewSet两个视图集基类
    GenericViewSet(ViewSetMixin, GenericAPIView),该分支严格满足资源接口
    
    ViewSet(ViewSetMixin, APIView),该分支满足的接口与资源Model类关系不是特别密切:登录接口、短信验证码接口

2)ReadOnlyModelViewSet,ModelViewSet两个视图集子类,就是做个一堆mixin与GenericViewSet相结合,

   自己在urls文件中配置as_view设置映射关系

猜你喜欢

转载自www.cnblogs.com/shaozheng/p/12121379.html