10 drf 视图基类(APIView、GenericAPIView)
一、APIView
form rest_framework.view.APIView
APIView
是REST framework提供的所有视图的基类,它是继承django的view类
APIView
与View的不同之处在于:
1. 传入视图方法中的是REST framework的Request对象,而不是Django的HttpRequest对象:
2. 视图方法可以返回REST framework的Response对象,视图会为响应数据设置解析方式(render),
3. 任何APIexception异常都会被捕获到,并且处理成合适的响应信息,返回给前端
4. APIView内部的也重写了父类的as_view()和view的as_view()不同,APIView在as_view()中局部禁用了csrf
5. 在进行dispath()分发前,会对请求进行身份认证,权限检查,浏览控制,在这里进行异常捕获
6. 多了一对类属性,可以完成视图类的局部配置:(renderer_class,parser_class···)
在APIView中以常规的类视图定义方法来实现get()\post()或者其他的一些请求方式的方法
举例:
from rest_framework.views import APIView
from . import models
from utils import serializer
from utils.response import APIResponse
# 通过APIview定义常规的类来完成get、post请求方式的方法---此处就只以群查数据的方式为例
class StudentsAPIView(APIView):
def get(self,request,*Args,**kwargs):
stu_query = models.Student.objects.all()
ser_list_obj = serializer.StudentSerializer(stu_query,many=True)
return APIResponse(restults = ser_list_obj.data)
二、GenericAPIView(通用视图类)
from rest_framework.generics import GenericAPIView
GenericAPIView:类继承了APIView类,主要增加操作序列化器和数据查询的方法,作用是为了引入下main的Mixins扩展类的执行提供方法支持。通常在使用时,可搭配一个或多个Mixins扩展类
1.提供的关于序列化器使用的属性和方法
属性:
serializer_class 指明视图使用的序列化器
方法:
1. get_serializer_class(self)
当出现一个视图类中嗲用多个序列化器时,那么可以通过条件判断在get_serializer_class方法中通过返回不同序列化器类名就可以让视图方法执行不通的序列化对象了。
2. get_serializer(self,*args,**kwargs)
返回序列化器对象,主要用来提供给Mixins扩展类使用,如果我们在视图中通过想要获取序列化器·对象,也可以直 接调用此方法
注意:该方法在提供序列化器对象的时,会像序列化器对象的context属性补充三个数据:
request 当前视图的请求对象
view 当前请求的类视图对象
format 当前请求期望返回的数据格式
2. 提供关于数据库查询的属性与方法
属性:
queryset 指明使用的数据查询集
方法:
1. get_queryset(self)
返回视图使用的查询集,主要用来提供给Mixins扩展类使用,是列表视图与详情视图获取数据的基础,默认返回 queryset属性
2. get_objects(self)
返回详情视图所需的模型类型数据对象,主要用来提供给Mixins扩展类使用
在视图中可以调用该方法获取详情信息的模型类对象
注意:若查询到模型类对象不存在,会返回404
该方法会默认使用APIView提供的check_object_permissions方法检查当前对象是否有权限被访问
3.举例:
以GenericAPIView类来实现get、post请求数据方式的方法
from rest_framework.generics import GenericAPIView
class StudentGenericAPIView(GenericAPIView):
# 提前申明号queryset,规定是从哪一个表类中读取数据
queryset = models.Student.objects.all()
# 提前申明用的序列化器是哪一个
serializer_class = serializer.StudentSerializer
def get(self,request,*Args,**kwargs):
# stu_query---self.get_queryset() 是取查询的数据对象集
# self.get_queryset() 当前类对象没有这个属性,一直去父类里面找,
# 调用的是GenericAPIView类中的get_queryset
# 我们会发现在父类GenericAPIView中的是判断了queryset是否有值,
# 当GenericAPIView中本来就有quetyset值得时候,他会直接报错得
# 当没有值得时候,才会进入get_queryset()执行
# 那我们有知道,如果没有值,就通过这个方法,我怎么知道在后端取查那个表中得数据呢?
# 源码中如果GenericAPIView类自身没有queryset值时,将self这个对象得queryset值赋给类中得queryset,然后开始调用方法
# 所以在上面我们要在用户请求成功,url匹配成功得时候,就将queryset赋值,
# 就是将要从那个表中查数据标识一下
stu_query = self.get_queryset()
# ser_list_obj---self.get_serializer(stu_query,many=True)
# 就是取序列化得序列化对象集
# 根据上述得理解就能得到原因,所以要在上面提前将从哪一个序列化器中序列化规定好
ser_list_obj = self.get_serializer(stu_query,many=True)
return APIResponse(restults = ser_list_obj.data)
4. 总结
queryset:是在用get_queryset()方法之前就要在当前视图类中定义好得,为得就是让get_quertset()方法知道,是那个表中得数据,然后返回queryset.all(),也就是所有得数据
query_set = self.get_queryset()
serializer_class:是在用get_serializer(query_set,many=True)方法前定义该视图使用得是哪一个序列化器,为得是让该方法知道是哪一个序列化器序列化得数据,返回正确得数据。(由于是以群查为例得,所以many=True)