• Django实现统一包装接口返回值数据格式


    前言

    最近实在太忙了,开始了一个新的项目,为了快速形成产品,我选择了Django来实现后端,然后又拿起了之前我封装了项目脚手架「DjangoStarter」

    由于前段时间我写了不少.NetCore的后端代码,对CRUD的接口开发又有了一些新的理解,所以肯定也要把DjangoStarter改造一番,改得更加顺手~

    题外话:话说我在前端终于真正用上react,不得不说 ts + react 真好用,「前端带师」的安利可真不错啊(妙啊

    正题

    准确来讲是搭配DjangoRestFramework来实现的,核心代码分为两部分,一个是错误处理包装,一个是响应包装renderer

    无论请求是否报错,都会被我们自定义的renderer包装。

    代码

    开始上代码吧~

    首先在项目里添加一个新的Python包,位置根据情况自行安排,我在DjangoStarter模板中的位置是utils/response,接下来的两个文件都会放在这个目录中

    第一个是错误处理的exception.py文件代码

    from typing import Dict
    
    from rest_framework.exceptions import ValidationError
    from rest_framework.views import exception_handler
    from rest_framework.views import Response
    from rest_framework.utils.serializer_helpers import ReturnDict
    from rest_framework import status
    
    
    def custom_handler(err: ValidationError, context: dict):
        # 先调用REST framework默认的异常处理方法获得标准错误响应对象
        response: Response = exception_handler(err, context)
    
        if response is None:
            return Response({
                'message': f'服务器错误:{err}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR, exception=True)
    
        else:
            res = {'message': response.reason_phrase}
            res.update(response.data)
            return Response(res, status=response.status_code, exception=True)
    

    然后是自定义renderer.py代码:

    from rest_framework.renderers import JSONRenderer
    
    
    class CustomRenderer(JSONRenderer):
        # 重构render方法
        def render(self, data, accepted_media_type=None, renderer_context=None):
            if renderer_context:
                # 响应的信息,成功和错误的都是这个
                # 成功和异常响应的信息,异常信息在前面自定义异常处理中已经处理为{'message': 'error'}这种格式
    
                # 如果返回的data为字典
                if isinstance(data, dict):
                    # 响应信息中有message和code这两个key,则获取响应信息中的message和code,并且将原本data中的这两个key删除,放在自定义响应信息里
                    # 响应信息中没有则将msg内容改为请求成功 code改为请求的状态码
                    msg = data.pop('message', '请求成功')
                    code = data.pop('code', renderer_context["response"].status_code)
                # 如果不是字典则将msg内容改为请求成功 code改为响应的状态码
                else:
                    msg = '请求成功'
                    code = renderer_context["response"].status_code
    
                # 自定义返回的格式
                ret = {
                    'message': msg,
                    'code': code,
                    'data': data,
                }
                # 返回JSON数据
                return super().render(ret, accepted_media_type, renderer_context)
            else:
                return super().render(data, accepted_media_type, renderer_context)
    

    关键的地方都注释了,很容易看懂

    包装出来每个接口的返回值就都是这个样子

    {
        "message": "msg",
        "code": 200,
        "data": {
            "data1": "123"
        }
    }
    

    配置

    为了让上面的代码发挥作用,还得配置一下RestFramework

    编辑settings.py文件,在REST_FRAMEWORK节点添加这两个配置,注意路径要和前面两个文件的路径一致。这里我是以DjangoStarter项目为例。

    REST_FRAMEWORK = {
        # 全局配置异常模块
        'EXCEPTION_HANDLER': 'utils.response.exception.custom_handler',
        # 修改默认返回JSON的renderer的类
        'DEFAULT_RENDERER_CLASSES': ('utils.response.renderer.CustomRenderer',),
    }
    

    现在就完成了~ 就是这么简单。

    (比AspNetCore包装返回值简单……)

    完整代码可以在GitHub上查看:https://github.com/Deali-Axy/DjangoStarter

    参考资料


    __EOF__

  • 本文作者: 程序设计实验室
  • 本文链接: https://www.cnblogs.com/deali/p/16094959.html
  • 关于博主: 公众号:程序设计实验室,欢迎交流~
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    腾讯云和阿里云4核8G云服务器多少钱一年和1个月费用对比
    在 macOS 上安装 Docker
    第一周pwn的题目
    瑞芯微 | 如何固定以太口地址为指定ip?
    ES的一些学习操作
    “12306” 的架构到底有多牛逼?
    前端部署项目
    会议信息管理系统SSM记录(六)
    java-php-python-航空订票管理系统计算机毕业设计
    使用 Helm 安装 极狐GitLab
  • 原文地址:https://www.cnblogs.com/deali/p/16094959.html