zoukankan      html  css  js  c++  java
  • 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扩展类使用,用来快速地实现列表视图与详情视图。

  • 相关阅读:
    ZOJ 2588 Burning Bridges
    POJ 1966 ZOJ 2182 Cable TV Network
    HDU 5348 MZL's endless loop
    HDU 5352 MZL's City
    Tarjan算法求解无向连通图的割点、割边、点双连通分量和边双连通分量的模板
    ZOJ 1119 SPF
    HDU 3452 Bonsai
    HDU 1520 Anniversary party
    POJ 2239 Selecting Courses
    POJ 1144 Network
  • 原文地址:https://www.cnblogs.com/chichung/p/9940697.html
Copyright © 2011-2022 走看看