Flask 工具封装 (Utils): 统一 API 响应

Flask 工具封装 (Utils): 统一 API 响应

本文档深入解析 OakAMC 项目中 app/utils 下关于 API 统一响应的处理逻辑。在前后端分离的项目中,这是极其重要的一环。

1. 为什么需要统一响应格式?

如果不进行封装,可能会出现每个人写代码风格不一致的情况:

  • 开发者 A: return jsonify({'code': 200, 'msg': 'ok'})
  • 开发者 B: return jsonify({'status': 'success', 'message': 'done'})
  • 开发者 C: return jsonify({'result': 0, 'error': None})

后果: 前端工程师需要为每个接口写适配器,导致维护噩梦。

因此,我们在 app/utils/api_response.py 中强制规定了唯一的返回结构。


2. 核心代码解析 (ApiResponse)

文件位置: app/utils/api_response.py

2.1 依赖关系 (ErrorCode)

为了避免魔术数字(Magic Numbers,如 400, 404),我们首先在 app/utils/error_code.py 中定义了枚举类:

class ErrorCode(object):
SUCCESS = 200 # 成功
BAD_REQUEST = 400 # 参数错误
NOT_LOGIN = 401 # 未登录
INFERROR = 1000 # 内部自定义逻辑错误

2.2 响应类封装逻辑

ApiResponse 类本身虽然很简单,但它的设计意图很明确:全静态方法 (All Static Method) 工具类

class ApiResponse(object):
# 基础方法:统一底层调用 jsonify
@staticmethod
def json(body={}):
return jsonify(body)
# 成功场景封装
@staticmethod
def success_data(data={}, msg='', show=True):
# 强制统一结构:code, error, message, data, show
return ApiResponse.json({
'code': ErrorCode.SUCCESS, # 固定为 200
'error': False, # 显式告知无误
'message': msg,
'data': data, # 数据载荷
'show': show # 控制前端是否弹窗提示
})
# 错误场景封装
@staticmethod
def error(msg='', show=True):
return ApiResponse.json({
'code': ErrorCode.BAD_REQUEST, # 固定为 400
'error': True,
'message': msg,
'show': show
})

2.3 关键设计点

  1. 静态方法: 不需要实例化 ApiResponse(),直接 ApiResponse.success_data() 调用,方便快捷。
  2. 强制结构: 无论成功还是失败,返回的JSON key 都是固定的(code, error, message),前端拦截器可以统一处理。
  3. show 字段: 这是一个典型的前后交互约定。后端告诉前端:“这个消息要不要弹窗给用户看?”
    • show=True: 前端把 message 弹个 Toast 出来。
    • show=False: 前端只记录日志,不打扰用户。

3. 实际使用案例

在路由函数 (routes.py) 中,我们不再直接使用 jsonify

场景一:查询成功

@bp.route('/users')
def get_users():
users = UserService.get_all()
# 优雅!直接返回数据
return ApiResponse.success_data(data=users, msg="查询成功")

场景二:参数错误

@bp.route('/login', methods=['POST'])
def login():
if not request.json.get('username'):
# 优雅!直接报错
return ApiResponse.bad_request(msg="用户名不能为空")

通过这种封装,整个项目的代码风格高度统一,任何新加入的开发者都能立即上手,且不容易犯错。