几种view以及他们之间的关系
View是Django中的
APIView
APIView是对Django中View的封装,和View相比,APIView大致有以下不同:
1.传递给处理方法的请求是DRF的Request实例,而不是Django的HttpRequest实例;
2.响应并返回的是DRF的Response对象,而不是Django的HttpResponse对象;
4.会对接收的请求进行身份认证、权限的检查以及限制访问次数。
APIView使用方法如下:
from rest_framework.views import APIView
from rest_framework.response import Response
class SchoolView(APIView):
def get(self, request, *args, **kwargs):
query_set = models.School.objects.all()
ser_obj = app01_serializers.SchoolSerializer(query_set, many=True)
return Response(ser_obj.data)
GenericApiView
GenericApiView继承于APIView,为常用的列表视图和详细视图提供了一些操作属性方法。
示例:
from rest_framework import generics
from rest_framework import mixins
class SchoolView(GenericAPIView, mixins.ListModelMixin):
queryset = models.School.objects.all()
serializer_class = app01_serializers.SchoolSerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
GenericAPIView对APIView再次封装,加入了以下功能:
- 加入queryset属性,可以直接设置这个属性,不必再将实例化的courses,再次传给seriliazer,系统会自动检测到。除此之外,可以重载get_queryset(),这样就不必设置’queryset=*’,这样就变得更加灵活,可以进行完全的自定义。
- 加入serializer_class属性与实现get_serializer_class()方法。两者的存在一个即可,通过这个,在返回时,不必去指定某个serilizer
- 设置过滤器模板:filter_backends(排序,过滤,搜索)
- 设置分页模板:pagination_class
- 加入 lookup_field=”pk”,以及实现了get_object方法: 这个用得场景不多,但十分重要。它们两者的关系同1,要么设置属性,要么重载方法。它们的功能在于获取某一个实例时,指定传进来的后缀是什么。
通常GenericAPIView不会单独使用,GenericAPIView需要和Mixins组合使用。
Mixin类中提供了许多用于对视图进行操作的方法,这些操作方法无须我们自己实现就可以使用了。比如,ListModelMixin
提供了一个list()
方法用于将Model的查询集响应给客户端。
在generics.py文件中还存在一些通用类,可以使代码的编写更加简单。
简化之后如下:
class SchoolView(ListCreateAPIView):
#使用通用类
queryset = models.School.objects.all()
serializer_class = app01_serializers.SchoolSerializer
GenericViewSet
GenericViewSet继承了ViewSetMixin和GenericAPIView,在ViewSetMixin类中重写了as_view方法,可以这样使用路由:
url(r'school/$', views.SchoolView.as_view({
"get": "list",
"post": "create",
})),
视图集ModelViewSet
集成了上面所有的类,非常好用
class SchoolView(ModelViewSet):
queryset = models.School.objects.all()
serializer_class = app01_serializers.SchoolSerializer
高级路由
route方法注册与绑定
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'school', views.SchoolView)
urlpatterns += router.urls
route中使用的一定要是ViewSet,用router.register的方法注册url可以很好的管理url,不会导致url过多而混乱。
补充:DRF中的Request和Resopnse
1. Request
在DRF中内置的Request类扩展了Django中的Request类,实现了很多方便的功能--如请求数据解析和认证等。
Request对象的数据是自动根据前端发送数据的格式进行解析之后的结果。
无论前端发送的哪种格式的数据,我们都可以以统一的方式读取数据。
常用属性
- .data
request.data 返回解析之后的请求体数据。类似于Django中标准的request.POST和 request.FILES属性,但提供如下特性:
包含了解析之后的文件和非文件数据
包含了对POST、PUT、PATCH请求方式解析后的数据
利用了DRF的parsers解析器,不仅支持表单类型数据,也支持JSON数据
- .query_params
request.query_params与Django标准的request.GET相同,只是更换了更正确的名称而已。
2 Response
DRF提供了一个响应类Response,使用该类构造响应对象时,响应的具体数据内容会被转换(render渲染)成符合前端需求的类型。
DRF提供了Renderer 渲染器,用来根据请求头中的Accept(接收数据类型声明)来自动转换响应数据到对应格式。如果前端请求中未进行Accept声明,则会采用默认方式处理响应数据,可以通过配置来修改默认响应格式。
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': ( # 默认响应渲染类
'rest_framework.renderers.JSONRenderer', # json渲染器
'rest_framework.renderers.BrowsableAPIRenderer', # 浏览API渲染器
)
}
构造方式
Response(data, status=None, template_name=None, headers=None, content_type=None)
参数:
data: 为响应准备的序列化处理后的数据;
status: 状态码,默认200;
template_name: 模板名称,如果使用HTMLRenderer 时需指明;
headers: 用于存放响应头信息的字典;
content_type: 响应数据的Content-Type,通常此参数无需传递,REST framework会根据前端所需类型数据来设置该参数。
常用属性:
- .data
传给response对象的序列化后,但尚未render处理的数据
- .status_code
状态码的数字
- .content
经过render处理后的响应数据
- 3. 状态码
返回状态信息。