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扩展类使用,用来快速地实现列表视图与详情视图。