DRF框架之APIView

在前面的文章中,我们后端序列化给前端都是以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
      • 通常此参数无需设置,会自动根据前端所需类型数据来设置该参数

 

部分代码展示:

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即可解决

posted @ 2020-07-18 21:36  小公瑾  阅读(2115)  评论(0编辑  收藏  举报