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

  • 相关阅读:
    波松分酒问题 C++求最优解. Anthony
    Effective STL 条款7 Anthony
    Effective STL 条款16 Anthony
    数据库设计经验之谈[转载]
    C#递归在dropdownlist显示树状
    多域名同主机js转向
    ASP.NET中常用的26个优化性能方法
    域名解析、子域名、cname别名指向、MX记录、泛域名与泛解析、域名绑定、域名转向
    C#数据库递归构造treeview树形结构
    ASP.NET多种方式生成高质量缩略图
  • 原文地址:https://www.cnblogs.com/xiaogongjin/p/13337628.html
Copyright © 2020-2023  润新知