Skip to content

第 09 章 统一响应与异常处理 ​

学习目标 ​

学完本章,你应该能:

  1. 理解为什么要统一响应格式
  2. 掌握 fba 的统一返回模型和返回方法
  3. 学会自定义响应状态码

一、为什么要统一响应格式 ​

想象一个项目,A 接口返回 {"code": 200, "msg": "成功", "data": {...}},B 接口返回 {"status": "ok", "result": {...}},C 接口直接返回数据。前端同学就得写三套解析逻辑,苦不堪言。

统一响应格式就是让所有接口返回结构一致,前端只需写一套解析逻辑。

fba 的统一响应结构长这样:

json
{
  "code": 200,       // 状态码
  "msg": "请求成功",  // 提示信息
  "data": null       // 业务数据
}

三个字段的含义:

字段含义
code业务状态码,200 表示成功
msg提示信息,给用户或前端看
data真正的业务数据,可为任意类型

统一响应的意义 ​

二、统一返回模型 ​

fba 提供了统一的 Pydantic 模型 ResponseModel:

python
class ResponseModel(BaseModel):
    code: int = 200
    msg: str = '请求成功'
    data: Any | None = None

使用时有两种写法(任选其一):

python
# 方式一:response_model 参数
@router.get('/test', response_model=ResponseModel)
def test():
    return ResponseModel(data={'test': 'test'})

# 方式二:-> 类型标注
@router.get('/test')
def test() -> ResponseModel:
    return ResponseModel(data={'test': 'test'})

三、Schema 模式(让文档显示 data 结构) ​

ResponseModel 有个小问题:Swagger 文档里看不出 data 里面是什么结构。于是 fba 提供了 ResponseSchemaModel:

python
class ResponseSchemaModel(ResponseModel, Generic[SchemaT]):
    data: SchemaT

用法:

python
@router.get('/test', response_model=ResponseSchemaModel[GetUserDetail])
def test():
    return ResponseSchemaModel[GetUserDetail](data=GetUserDetail(...))

这样 Swagger 文档就能显示 data 里的完整字段结构了。

建议:查询类接口用 ResponseSchemaModel(让文档更清晰),其他接口用 ResponseModel 即可。

两种返回模型的区别 ​

四、统一返回方法(response_base) ​

fba 提供了全局响应实例 response_base,极大简化返回写法。它有三个方法:

方法用途默认返回
success()成功响应code=200, msg="请求成功"
fail()失败响应code=400, msg="请求错误"
fast_success()大 JSON 快速成功同 success,但解析性能更高

用法示例:

python
@router.get('/test')
def test() -> ResponseModel:
    return response_base.success(data={'test': 'test'})

@router.get('/test')
def test() -> ResponseModel:
    return response_base.fail(msg='参数错误')

注意:这三个都是同步方法(非 async)。因为它们不涉及 IO 操作,定义为异步反而增加协程开销。

五、自定义响应状态码 ​

实际项目中,状态码往往需要按业务约定调整。fba 内置了 CustomResponseCode 和 CustomResponse 来定义自己的状态码:

python
# 定义自定义响应
res = CustomResponse(code=0, msg='成功')

# 用法一:直接构造
return ResponseModel(code=res.code, msg=res.msg, data={'test': 'test'})

# 用法二:传给 response_base
return response_base.success(res=res, data={'test': 'test'})

六、驼峰返回 ​

前面提过,fba 默认用 Python 下划线命名(user_name),但前端多用小驼峰(userName)。fba 通过 SchemaBase 自动转换,返回给前端的数据自动变成小驼峰,无需手动处理。

七、异常处理 ​

fba 对异常有统一处理机制(在 common/response/ 目录下)。核心思路:

  • 业务异常统一抛出,统一捕获,统一转成 {code, msg, data} 格式返回
  • 定义了标准的错误码体系,避免散落的 raise Exception('xxx')

异常处理流程 ​

完整异常处理细节可参考官方文档和源码,核心记住一点:异常也要走统一格式。

八、常见疑问 ​

Q1:success() 和 fast_success() 有什么区别?fast_success() 专为返回大型 JSON 设计,能大幅提升解析性能。普通接口用 success() 即可,大数据量场景用 fast_success()。

Q2:为什么返回方法不是异步的? 因为这些方法只是构造数据对象,不涉及 IO(不查数据库、不读文件),定义为同步即可,还能省去协程调度开销。

本章小结 ​

关键要点回顾:

  • 统一响应格式:{code, msg, data}
  • 两个返回模型:ResponseModel(通用)、ResponseSchemaModel(文档显示 data 结构)
  • 返回方法:response_base.success() / fail() / fast_success()
  • 状态码可用 CustomResponse 自定义
  • 返回数据自动转小驼峰

下一步: 第 10 章讲数据库会话与事务,这是写"增删改"操作必须掌握的核心概念。


对应官方文档:接口响应(backend/reference/response.html)