• DRF基类APIView的子类GenericAPIView


    DRF的基类是APIView类,GenericAPIView类是APIView类的子类。

    GenericAPIView类有什么存在的意义呢?

    其实,

    他主要提供了两个用处:

    1.提供关于数据库查询的属性与方法

    2.提供关于序列化器使用的属性与方法

    =================================================================================================================

    详解:

    先看一段小代码比较好理解,(继承APIView与继承GenericAPIView的两种不同的写法,查询多条数据时)

    继承APIView的写法:

    class DepartmentListAPIView(APIView):
        def get(self,request):
            """查询多条数据"""
            dep = Department.objects.all()
            # 创建序列化器对象
            serializer = DepartmentSerializer(instance=dep,many=True)
            # 序列化:对象->字典
            data_dict = serializer.data
            # DRF的Response对象可以把字典转换为请求头指定的格式返回
            return Response(data=data_dict)

    继承GenericAPIView的写法:

    class DepartmentListAPIView(GenericAPIView):
        # querset与serializer_class是固定名字的!一定要指定
        # queryset指定数据库全部数据的查询集
        queryset = Department.objects.all()
        # serializer_class指定序列化器
        serializer_class = DepartmentSerializer
        def get(self,request):
            """查询多条数据"""
            dep = self.get_queryset()
            serializer = self.get_serializer(dep,many=True)
            data_dict = serializer.data
            return Response(data=data_dict)

     

    1.提供关于数据库查询的属性与方法:

    上面例子中,get_queryset()的方法,可以取得数据库查询结果的查询集queryset的内容。(注意,一定要通过get_query取得数据库查询的结果后再传给序列化器,不能直接传self.queryset给序列化器,因为get_query的源码还有“Ensure queryset is re-evaluated on each request.”这一个步骤。)

    2.提供关于序列化器使用的属性与方法

    上面的列子中,get_serializer()的方法,实际上就是取类属性serializer_class的值

     

    • 更多的继承APIView与继承GenericAPIView的写法:

    继承APIView的写法:

    class DepartmentListAPIView(APIView):
        def get(self,request):
            """查询多条数据"""
            dep = Department.objects.all()
            # 创建序列化器对象
            serializer = DepartmentSerializer(instance=dep,many=True)
            # 序列化:对象->字典
            data_dict = serializer.data
            # DRF的Response对象可以把字典转换为请求头指定的格式返回
            return Response(data=data_dict)
    
        def post(self,request):
            """新增一条数据"""
            # DRF的Request对象直接把接受到的值转换为字典
            data_dict = request.data
            # 创建序列化器对象
            serializer = DepartmentSerializer(instance=None,data=data_dict)
            # 校验校验不通过,抛异常(反序列化的功能)
            serializer.is_valid(raise_exception=True)
            # 反序列化,把字典的数据存进数据库
            serializer.save()
            # restful风格,新增要返回新增数据的那一列内容。用了序列化,把对象转换为字典,同时Response处理。
            return Response(data=serializer.data)
    
    
    class DepartmentDetailAPIView(APIView):
        def get(self,request,pk):
            """查询一条数据"""
            # 查询出该条数据的对象
            try:
                dep = Department.objects.get(id=pk)
            except Department.DoesNotExist:
                return HttpResponse(status=status.HTTP_404_NOT_FOUND)
            # 创建序列化器对象
            serializer = DepartmentSerializer(instance=dep)
            # 序列化,把对象转换为字典,同时Response根据请求头返回相应的格式
            return Response(data=serializer.data)
    
        def post(self,request,pk):
            """修改部门"""
            # DRF的Request对象直接把接受到的值转换为字典
            data_dict = request.data
            # 查询出要修改的数据
            try:
                dep = Department.objects.get(id=pk)
            except Department.DoesNotExist:
                return HttpResponse(status=404)
            # 创建序列化器对象
            serializer = DepartmentSerializer(instance=dep,data=data_dict)
            # 反序列化,校验参数是否正确,若不正确,抛异常
            serializer.is_valid(raise_exception=True)
            # 反序列化,把字典的数据存进数据库
            serializer.save()
            # 序列化,把对象转换为字典。同时DRF的Response对象根据请求头返回相应的格式
            return Response(serializer.data)
    
        def delete(self,request,pk):
            """删除一个部门"""
            try:
                dep = Department.objects.get(id=pk)
            except Department.DoesNotExist:
                return HttpResponse(status=404)
            dep.delete()
            return Response(status=status.HTTP_204_NO_CONTENT)

    继承GenericAPIView的写法:

    class DepartmentListAPIView(GenericAPIView):
        # querset与serializer_class是固定名字的!
        # queryset指定数据库全部数据的查询集
        queryset = Department.objects.all()
        # serializer_class指定序列化器
        serializer_class = DepartmentSerializer
    
        def get(self,request):
            """查询多条数据"""
            dep = self.get_queryset()
            serializer = self.get_serializer(instance=dep,many=True)
            data_dict = serializer.data
            return Response(data=data_dict)
    
        def post(self,request):
            """新增一条数据"""
            data_dict = request.data
            serializer = self.get_serializer(instance=None,data=data_dict)
            serializer.is_valid(raise_exception=True)
            serializer.save()
            return Response(serializer.data)
    
    
    class DepartmentDetailAPIView(GenericAPIView):
    
        queryset = Department.objects.all()
        serializer_class = DepartmentSerializer
    
        def get(self,request,pk):
            """查询一条数据"""
            dep = self.get_object()  # 有主键用get_object(),get_object()方法根据pk参数查找queryset中的数据对象
            serializer = self.get_serializer(instance=dep)
            return Response(data=serializer.data)
    
        def post(self,request,pk):
            """修改部门"""
            data_dict = request.data
            dep = self.get_object()
            serializer = self.get_serializer(instance=dep,data=data_dict)
            serializer.is_valid(raise_exception=True)
            serializer.save()
            return Response(serializer.data)
    
        def delete(self,request,pk):
            """删除一个部门"""
            dep = self.get_object()
            dep.delete()
            return Response(status=status.HTTP_204_NO_CONTENT)
    • 总结:

    从上面的代码可以看出,继承APIView和继承GenerciAPIView的代码量基本差不多。那么GenericAPIView这个类有什么实质的用处呢?

    其实,

    他是只是为了提供几种方法给它的扩展类而已,GenericAPIView通常结合一个或多个Mixin扩展类使用,用来快速地实现列表视图与详情视图。

  • 相关阅读:
    计算机网络知识技能水平的测评试题
    Socket与系统调用深度分析
    学习构建调试Linux内核网络代码的环境MenuOS系统
    深入学习socket网络编程,以java语言为例
    网络配置工具iproute2和net-tools的基本原理和基本使用方法
    Linux系统学习总结报告
    结合中断上下文切换和进程上下文切换分析Linux内核的一般执行过程
    深入理解系统调用-40号调用
    基于mykernel2.0 编写一个操作系统内核
    交互式多媒体图书平台的设计与实现
  • 原文地址:https://www.cnblogs.com/chichung/p/9940697.html
Copyright © 2020-2023  润新知