在前面的文章中,我们后端序列化给前端都是以json数据返回,反序列化(post、put)也以json数据格式输入,如果我们反序列化输入的数据也想以application/x-www-form-urlencoded或者其它的格式输入呢?又或者返回的数据想以html页面的方式展示呢?
在django的视图中,我们都知道需要继承View这个类,在使用DRF框架后,我们的视图可以来继承APIView,它对django中的View做了一系列拓展,如:认证、授权、限流和不同请求数据的解析等等
- 继承Django中的View
- APIView与View的不同之处
- 传入到视图方法中的是Request对象,而不是Django的HttpRequest对象
- 视图方法可以返回Response对象,会为响应数据处理(render)为符合前端要求的格式
- 任何APIException异常都会被捕获到,并且处理成合适的响应信息
- 在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制
- 常用类属性
- authentication_classes列表或元组,身份认证类
- permission_classes列表或元组,权限检查类
- throttle_classes列表或元组,流量控制类
一、引入方式
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status
二、序列化Response<->Accept
1.Response
前面我们一般都使用的是JsonResponse来进行序列化输出,使用了APIView之后,我们可以使用Response序列化输出,它有以下特性:
- 对Django中的HttpResponse进行了拓展
- 会根据请求头中的Accept,自动转化响应数据到对应格式
- 如果请求头中未设置Accept,则会采用默认方式处理响应数据(默认返回json格式的数据)
- 可以指定响应默认渲染类
- Response(data, status=None, template_name=None, headers=None, content_type=None)
- 参数说明
- data
- 序列化处理后的数据
- 一般为serializer.data(python基本数据类型:字典、嵌套字典的列表)
- status
- 状态码,默认为200
- template_name
- 模板名称,使用HTNLRenderer渲染时需指明
- headers
- 用于存放响应头信息的字典
- content_type
- 响应头中的Content-Type
- 通常此参数无需设置,会自动根据前端所需类型数据来设置该参数
- data
部分代码展示:
from django.http import Http404 from django.db import connection from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from .models import Projects from .serializers import ProjectsModelSerializer class ProjectsPage(APIView): ''' 类视图 ''' def get_object(self, pk): try: obj = Projects.objects.get(id__exact=pk) except Exception: raise Http404("参数错误") return obj def get(self, request, pk=None): if pk: obj = self.get_object(pk) serializer_obj = ProjectsModelSerializer(instance=obj) return Response({'code': 0, 'res': "success", 'msg': serializer_obj.data}, status=status.HTTP_200_OK) else: qs = Projects.objects.all() serializer_obj = ProjectsModelSerializer(instance=qs, many=True) return Response({'code': 0, 'res': "success", 'msg': serializer_obj.data}, status=status.HTTP_200_OK)
前端展示:
postman展示:
1.不指定Accept
1.指定Accept
2.渲染类
我们不指定Accept的使用,默认为返回json数据,但这又是为什么呢?为什么不会返回别的类型数据呢?在drf的全局配置中,DEFAULTS属性值有一个渲染类的配置
从该列表我们知道,不指定时为默认返回json,如果我们想返回除了JSONRenderer和BrowsableAPIRenderer之外的格式数据时,就需要将该列表在项目下的settings.py中的REST_FRAMEWORK属性中进行重写
三、反序列化Request<->Content-Type
1.Request
现在我们的需求不仅仅是只使用json传参,也需要支持x-www-form-urlencoded传参,在django中,获取json的参数使用的为request.body,获取x-www-form-urlencoded参数使用的为request.POST,获取查询字符串参数使用的为request.GET,那么针对post这样的请求,如果想同时支持json和x-www-form-urlencoded传参,有没有更好的方式呢?答案是有的,我们使用drf框架,视图继承APIView时,request就不是原来的HttpRequest对象了,而是drf中的Request对象了,我们打断点看一下
当我们给post请求传入json或者x-www-form-urlencoded时,获取参数的方式都是request.data,查询字符串变成了request.query_params,因此我们可以轻轻松松地实现以上需求
针对Request,总结如下特性:
- 对Django中的HttpRequest进行了拓展
- 会根据请求头中的Content-Type,自动进行解析
- 无论前端发送的哪种格式的数据,都可以以相同的方式读取
- request.data
- 类似于Django中的request.POST和request.FILES
- 可以对POST、PUT、PATCH的请求体参数进行解析
- 不仅支持form传参,也支持json格式传参
- request.query_params
- 类似于Django中的request.GET
- 获取查询字符串参数
- 支持Django HttpRequest中所有的对象和方法
from django.http import Http404 from django.db import connection from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from .models import Projects from .serializers import ProjectsModelSerializer class ProjectsPage(APIView): ''' 类视图 ''' def post(self, request): serializer_check_obj = ProjectsModelSerializer(data=request.data) if not serializer_check_obj.is_valid(): return Response({"code": 1, "res": "error", "msg": serializer_check_obj.errors}, status=status.HTTP_400_BAD_REQUEST) serializer_check_obj.save() return Response({'code': 0, 'res': "success", 'msg': serializer_check_obj.data}, status=status.HTTP_201_CREATED)
postman展示:
1.以json传参
2.以表单传参
2.解析类
同样的,drf的配置中也有关于解析类的配置,如果需要拓展其它解析方式,依然可以重写
四、踩坑记录
1.抛出问题:
2.问题解决:
如果遇到该类问题,报错提示api.html不存在,则需要将项目下settings.py模块中TEMPLATES下的APP_DIRS设置为True即可解决