Skip to content

Commit 3d06d98

Browse files
committed
update docs
1 parent 1951f3e commit 3d06d98

File tree

1 file changed

+76
-31
lines changed

1 file changed

+76
-31
lines changed

docs/guide/reference/response.md

Lines changed: 76 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,51 +4,32 @@ title: 接口响应
44

55
我们为 FBA 开发了十分灵活且健全的接口响应系统,它同时适用于任何 FastAPI 应用
66

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-
217
## 统一返回模型
228

239
在常规 web 应用开发中,通常情况下,响应结构总是统一的,但在 FastAPI 的官方教程中,并没有提示我们该如何这样做,其实,这很简单,
2410
只需我们提供一个统一的 pydantic 模型
2511

2612
```python
2713
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-
3114
code: int = CustomResponseCode.HTTP_200.code
3215
msg: str = CustomResponseCode.HTTP_200.msg
3316
data: Any | None = None
3417
```
3518

36-
以上是我们在 FBA 中的内部实现,由于我们使用的是 pydantic-v2,所以,`json_encoders` 可能暂时无法按预期工作;
37-
3819
以下是使用此模型进行返回的示例(遵循 FastAPI 官方教程),`response_model` 参数和 `->` 类型我们只需选择其中一种方式即可,因为
3920
FastAPI 会在内部自动解析并获取最终响应结构
4021

4122
`response_model` 参数
4223

43-
```python{1}
24+
```python{1,3}
4425
@router.get('/test', response_model=ResponseModel)
4526
def test():
4627
return ResponseModel(data={'test': 'test'})
4728
```
4829

4930
`->` 类型
5031

51-
```python{2}
32+
```python{2,3}
5233
@router.get('/test')
5334
def test() -> ResponseModel:
5435
return ResponseModel(data={'test': 'test'})
@@ -63,31 +44,61 @@ ResponseModel 做为统一响应模型,你会在 Swagger 文档得到(如图
6344

6445
显然,我们无法获取响应 Schema 中的 data 结构,前端同事找到你,你会告诉他们,你请求一下不就行了?(没毛病,但显然不太友好),下面就是我们的解决办法
6546

47+
```python
48+
class ResponseSchemaModel(ResponseModel, Generic[SchemaT]):
49+
data: SchemaT
50+
```
51+
52+
这是我们创建的用于 Schema 模式的统一返回模型,它的用法与 `ResponseModel` 基本相似
53+
54+
`response_model` 参数
55+
6656
```python{1,3}
67-
@router.get('/test', response_model=ResponseSchemaModel[GetApiListDetails])
57+
@router.get('/test', response_model=ResponseSchemaModel[GetApiDetail])
6858
def test():
69-
return ResponseSchemaModel[GetApiListDetails](data=GetApiListDetails(...))
59+
return ResponseSchemaModel[GetApiDetail](data=GetApiDetail(...))
7060
```
7161

72-
我们可以看到,这里其实和统一响应模型 ResponseModel 差不多,关键就在于我们这里多了一个 `[xxxSchema]`,没错,这就是关键,此时我们再来看一眼
73-
Swagger 文档
62+
`->` 类型
63+
64+
```python{2,3}
65+
@router.get('/test')
66+
def test() -> ResponseSchemaModel[GetApiDetail]:
67+
return ResponseSchemaModel[GetApiDetail](data=GetApiDetail(...))
68+
```
69+
70+
此时我们再来看一眼 Swagger 文档
7471

7572
![response_schema_model](/images/response_schema_model.png)
7673

77-
我们可以看到,响应 Schema 中的 data 已经包含我们的响应体结构了,响应体结构正式解析的 `[]` Schema 模型,它们是对应的,如果返回的数据结构与
74+
我们可以看到,响应 Schema 中的 data 已经包含我们的响应体结构了,响应体结构正是解析的 `[]` 中的 Schema 模型,它们是对应的,如果返回的数据结构与
7875
Schema 不一致,将引发解析错误
7976

80-
我们建议将这种方式仅用于查询接口,如果你不需要这种文档/验证,你完全可以不使用它,而是使用更加开放的统一响应模型 ResponseModel
77+
==我们建议将这种方式仅用于查询接口==,如果你不需要这种文档/验证,你完全可以不使用它,而是使用更加开放的统一响应模型
78+
ResponseModel
8179

8280
## 统一返回方法
8381

84-
`response_base` 是我们做的全局基础响应实例,此实例包含三个开放式方法,分别为:`success()``fail()``fast_seccess()`
82+
`response_base` 是我们做的全局响应实例,它大大简化了响应返回方式,用法如下:
83+
84+
```python{3,8}
85+
@router.get('/test')
86+
def test() -> ResponseModel:
87+
return response_base.success(data={'test': 'test'})
88+
89+
90+
@router.get('/test')
91+
def test() -> ResponseSchemaModel[GetApiDetail]:
92+
return response_base.success(data=GetApiDetail(...))
93+
```
94+
95+
此实例包含三个返回方法:`success()``fail()``fast_sucess()`
8596

8697
::: warning
8798
它们都是同步方法,而不是异步。因为这些返回方法并不涉及 io 操作,所以,定义为异步,不但没有性能提升,反而增加了异步协程的开销
8899
:::
89100

90-
### success()
101+
`success()`
91102

92103
此方法通常作为默认响应方法使用,默认返回信息如下
93104

@@ -99,7 +110,7 @@ Schema 不一致,将引发解析错误
99110
}
100111
```
101112

102-
### fail()
113+
`fail()`
103114

104115
此方法通常在接口响应信息为失败时使用,默认返回信息如下
105116

@@ -111,7 +122,7 @@ Schema 不一致,将引发解析错误
111122
}
112123
```
113124

114-
### fast_success()
125+
`fast_success()`
115126

116127
此方法通常仅用于接口返回大型 json 时,可为 json 解析性能带来质的提升,默认返回信息如下
117128

@@ -122,3 +133,37 @@ Schema 不一致,将引发解析错误
122133
"data": null
123134
}
124135
```
136+
137+
## 响应状态码
138+
139+
在文件 `backend/common/response/response_code.py` 中内置了多种定义响应状态码的方式,我们可以根据 `CustomResponseCode`
140+
`CustomResponse` 定义自己需要的的响应状态码,因为在实际项目中,响应状态码并没有统一的标准
141+
142+
当我们定义好自定义响应状态码之后,可以像下面这样使用
143+
144+
```python{3-4}
145+
@router.get('/test')
146+
def test() -> ResponseModel:
147+
res = CustomResponse(code=0, msg='成功')
148+
return ResponseModel(res=res, data={'test': 'test'})
149+
```
150+
151+
## 驼峰返回
152+
153+
我们默认使用 python 下划线命名法进行数据返回,但是,在实际工作中,前端目前大多使用小驼峰命名法,所以,我们就需要对此进行一些修改来适配前端工程,在文件
154+
`backend/common/schema.py` 中,我们有一个 `SchemaBase` 类,它是我们的全局 Schema 基础类,修改如下:
155+
156+
```python
157+
class SchemaBase(BaseModel):
158+
model_config = ConfigDict(
159+
populate_by_name=True, # [!code ++] 允许通过原始字段名或别名进行赋值
160+
alias_generator=to_camel, # [!code ++] 自动将字段名转换为小驼峰
161+
use_enum_values=True,
162+
json_encoders={datetime: lambda x: x.strftime(settings.DATETIME_FORMAT)},
163+
)
164+
```
165+
166+
其中,`to_camel` 方法引入自
167+
pydantic,详情:[pydantic.alias_generators](https://docs.pydantic.dev/latest/api/config/#pydantic.alias_generators)
168+
169+
完成以上修改后,Schema 模式和返回数据将自动转为小驼峰命名

0 commit comments

Comments
 (0)