|
2 | 2 | title: 接口响应
|
3 | 3 | ---
|
4 | 4 |
|
5 |
| -coming soon... |
| 5 | +我们为 FBA 开发了十分灵活且健全的接口响应系统,它同时适用于任何 FastAPI 应用 |
| 6 | + |
| 7 | +## 响应状态码 |
| 8 | + |
| 9 | +在文件 `backend/common/response/response_code.py` 中内置了多种定义响应状态码的方式,我们可以根据 `CustomResponseCode` 和 |
| 10 | +`CustomResponse` 定义自己需要的的响应状态码,因为在实际项目中,响应状态码并没有统一的标准 |
| 11 | + |
| 12 | +当我们定义好自定义响应状态码之后,可以向下方这样使用 |
| 13 | + |
| 14 | +```python{3-4} |
| 15 | +@router.get('/test') |
| 16 | +def test() -> ResponseModel: |
| 17 | + res = CustomResponse(code=0, msg='成功') |
| 18 | + return ResponseModel(res=res, data={'test': 'test'}) |
| 19 | +``` |
| 20 | + |
| 21 | +## 统一返回模型 |
| 22 | + |
| 23 | +在常规 web 应用开发中,通常情况下,响应结构总是统一的,但在 FastAPI 的官方教程中,并没有提示我们该如何这样做,其实,这很简单, |
| 24 | +只需我们提供一个统一的 pydantic 模型 |
| 25 | + |
| 26 | +```python |
| 27 | +class ResponseModel(BaseModel): |
| 28 | + # TODO: json_encoders 配置失效: https://github.com/tiangolo/fastapi/discussions/10252 |
| 29 | + model_config = ConfigDict(json_encoders={datetime: lambda x: x.strftime(settings.DATETIME_FORMAT)}) |
| 30 | + |
| 31 | + code: int = CustomResponseCode.HTTP_200.code |
| 32 | + msg: str = CustomResponseCode.HTTP_200.msg |
| 33 | + data: Any | None = None |
| 34 | +``` |
| 35 | + |
| 36 | +以上是我们在 FBA 中的内部实现,由于我们使用的是 pydantic-v2,所以,`json_encoders` 可能暂时无法按预期工作; |
| 37 | + |
| 38 | +以下是使用此模型进行返回的示例(遵循 FastAPI 官方教程),`response_model` 参数和 `->` 类型我们只需选择其中一种方式即可,因为 |
| 39 | +FastAPI 会在内部自动解析并获取最终响应结构 |
| 40 | + |
| 41 | +`response_model` 参数 |
| 42 | + |
| 43 | +```python{1} |
| 44 | +@router.get('/test', response_model=ResponseModel) |
| 45 | +def test(): |
| 46 | + return ResponseModel(data={'test': 'test'}) |
| 47 | +``` |
| 48 | + |
| 49 | +`->` 类型 |
| 50 | + |
| 51 | +```python{2} |
| 52 | +@router.get('/test') |
| 53 | +def test() -> ResponseModel: |
| 54 | + return ResponseModel(data={'test': 'test'}) |
| 55 | +``` |
| 56 | + |
| 57 | +## Schema 模式 |
| 58 | + |
| 59 | +上面我们已经讲解了统一返回模型,但是,FastAPI 中的优势之一好包括,完全自动的 openAPI 以及文档,如果我们全局使用 |
| 60 | +ResponseModel 做为统一响应模型,你会在 Swagger 文档得到(如图所示) |
| 61 | + |
| 62 | + |
| 63 | + |
| 64 | +显然,我们无法获取响应 Schema 中的 data 结构,前端同事找到你,你会告诉他们,你请求一下不就行了?(没毛病,但显然不太友好),下面就是我们的解决办法 |
| 65 | + |
| 66 | +```python{1,3} |
| 67 | +@router.get('/test', response_model=ResponseSchemaModel[GetApiListDetails]) |
| 68 | +def test(): |
| 69 | + return ResponseSchemaModel[GetApiListDetails](data=GetApiListDetails(...)) |
| 70 | +``` |
| 71 | + |
| 72 | +我们可以看到,这里其实和统一响应模型 ResponseModel 差不多,关键就在于我们这里多了一个 `[xxxSchema]`,没错,这就是关键,此时我们再来看一眼 |
| 73 | +Swagger 文档 |
| 74 | + |
| 75 | + |
| 76 | + |
| 77 | +我们可以看到,响应 Schema 中的 data 已经包含我们的响应体结构了,响应体结构正式解析的 `[]` 的 Schema 模型,它们是对应的,如果返回的数据结构与 |
| 78 | +Schema 不一致,将引发解析错误 |
| 79 | + |
| 80 | +我们建议将这种方式仅用于查询接口,如果你不需要这种文档/验证,你完全可以不使用它,而是使用更加开放的统一响应模型 ResponseModel |
| 81 | + |
| 82 | +## 统一返回方法 |
| 83 | + |
| 84 | +`response_base` 是我们做的全局基础响应实例,此实例包含三个开放式方法,分别为:`success()`、`fail()`、`fast_seccess()` |
| 85 | + |
| 86 | +::: warning |
| 87 | +它们都是同步方法,而不是异步。因为这些返回方法并不涉及 io 操作,所以,定义为异步,不但没有性能提升,反而增加了异步协程的开销 |
| 88 | +::: |
| 89 | + |
| 90 | +### success() |
| 91 | + |
| 92 | +此方法通常作为默认响应方法使用,默认返回信息如下 |
| 93 | + |
| 94 | +```json |
| 95 | +{ |
| 96 | + "code": 200, |
| 97 | + "msg": "请求成功", |
| 98 | + "data": null |
| 99 | +} |
| 100 | +``` |
| 101 | + |
| 102 | +### fail() |
| 103 | + |
| 104 | +此方法通常在接口响应信息为失败时使用,默认返回信息如下 |
| 105 | + |
| 106 | +```json |
| 107 | +{ |
| 108 | + "code": 200, |
| 109 | + "msg": "请求成功", |
| 110 | + "data": null |
| 111 | +} |
| 112 | +``` |
| 113 | + |
| 114 | +### fast_success() |
| 115 | + |
| 116 | +此方法通常仅用于接口返回大型 json 时,可为 json 解析性能带来质的提升,默认返回信息如下 |
| 117 | + |
| 118 | +```json |
| 119 | +{ |
| 120 | + "code": 200, |
| 121 | + "msg": "请求成功", |
| 122 | + "data": null |
| 123 | +} |
| 124 | +``` |
0 commit comments