返回文章列表文章索引阅读全文
STARBLOG / 阅读手记
Django

Django统一包装接口返回数据格式

前言 最近实在太忙了,开始了一个新的项目,为了快速形成产品,我选择了Django来实现后端,然后又拿起了之前我封装了项目脚手架「DjangoStarter」。 由于前段时间我写了不少.NetCore的后端代码,对CRUD的接口开发又有了一些新的理解,所以肯定也要把DjangoStarter改造一番,改得更加顺手~ 题外话:话说我在前端终于真正用上react,不得不说 ts + react 真好用,

曦远 (DealiAxy)约 9 分钟
目录5 个章节

前言

最近实在太忙了,开始了一个新的项目,为了快速形成产品,我选择了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:
        # 因为RestFramework默认的报错信息是 detail 字段,这里取出系统的报错信息
        msg = response.data.pop('detail', response.reason_phrase)
        res = {'message': msg}
        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_

Django统一包装接口返回数据格式

本文作者:
程序设计实验室
版权声明:
本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

相关文章

一小时完成后台开发:DjangoRestFramework开发实践

DjangoRestFramework开发实践 在这之前我写过一篇关于Django与Drf快速开发实践的博客,Django快速开发实践:Drf框架和xadmin配置指北,粗略说了一下Drf配置和基本使用,不过里面只是涉及到最基本的CRUD,在正常的后端开发中涉及的诸如认证和权限、消息队列、缓存之类的操作,上一篇博客并没有涉及,这次开发我仔细了看了官方文档的这几个部分,把这部分的功能完善了起来。 D

2021-12-18 · Django · 约 1 分钟

Django+Taro项目实现企业微信登录

前言 还是最近在做的一个小项目,后端用的是Django搭配RestFramework做接口,前端第一次尝试用京东开源的Taro框架来做多端(目前需要做用于企业微信的H5端和微信小程序) 本文记录一下企业微信登录的流程,上周看文档看得头晕晕的,其实很简单,封装好了就几行代码的事~ 两种方式 一种是先拼接好登录要用的地址authorize_url,回调地址设置成h5应用的网页入口,然后把authori

2022-04-08 · Django · 约 1 分钟

Django数据库性能优化之使用Python集合操作

前言 最近有个新需求: 人员基础信息(记作人员A),10w 某种类型的人员信息(记作人员B),1000 要求在后台上(Django Admin)分别展示:已录入A的人员B列表、未录入的人员B列表 团队的DBA提议使用视图可以解决这个问题(不愧是搞数据库的) PS:起先我觉得Django的Model是直接管理数据库表的,使用Model来映射数据库模型怕是有一定的麻烦,不过查了一下资料发现并不会~ 只

2022-08-26 · Django · 约 1 分钟

讨论

共 0 条

良言一句三冬暖,恶语伤人六月寒。

加载评论中…