多个request-body
class Item1(BaseModel):
name: str
class Item2(BaseModel):
name: str
@app.post('/request_body01')
def request_body01(*, item1: Item1, item2: Item2):
return [item1, item2]
@app.post("/request_body02")
def request_body02(*, item1: Item1, item2: Item2, item3: str = Body(...)):
return [item1, item2, item3]
接受多个request-body的方法除了使用继承BaseModel,还可以使用FastApi提供的Body方法,和上一个学习目录中提到Path,Query类似,当定义成str类型的,可以使用min_length, max_length限制,当定义成int类型时,可以使用ge,gt,le,lt等限制。除此之外,Body还提供了一个embed的参数,用于只有request-body参数时,将key嵌套进request-body中,形如:
@app.post("/request_body03")
def request_body03(item1: Item1 = Body(..., embed=True)):
return item1
这种情况下,调用时传入的request-body是{“item1”: {"name": "***"}}而不是{"name": "***"}
BaseModel中Field
接受request-body参数时可以用继承与BaseModel的类来实现,但是没有对类中的参数的数据校验,而Field提供了这样的功能。
注意:Field与Body,Query,Path的不同之处在于Field引自于Pydantic而不是FastApi。
class Item3(BaseModel):
name: str = Field(..., min_length=3)
age: int = Field(..., ge=0)
@app.post("/request_body04")
def request_body04(item: Item3):
return item
BaseModel中的嵌套模型
class Item3(BaseModel):
list1: list = []
list2: List = []
list3: List[int] = [1]
数组类型的定义可以使用list和由typing导入的List,但是只要指定数组内元素的数据类型,只能使用List来声明。
class Item4(BaseModel):
set1: set = set()
set2: Set = set()
set3: Set[str] = set()
集合的定义和数组一样
class Item5(BaseModel):
set1: set = set()
set2: Set = set()
set3: Set[str] = set()
list1: Item4 = None
list2: List[Item4] = None
也可以使用别的model类来声明自己的属性,也可以定义成嵌套类型的子属性,支持多层嵌套。
@app.post("/request_body06")
def reuqest_body06(item: List[Item1]):
return item
上述方式接受一个数据类型的model而不是字典类型的model。
@app.post("/request_body07")
def reuqest_body07(dict1: Dict[str, int]):
return dict1
当不确定具体的key的时候,可以使用Dict的方法
Api文档增加样例
class Item6(BaseModel):
name: str = Field(..., example="wang")
age: int = Field(..., example=1)
class Item7(BaseModel):
sex: int
class Config:
schema_extra = {
"example": {"sex": 1}
}
@app.post("/request_body08")
def request_body08(item1: Item6, item2: Item7):
return [item1, item2]
使用Field的example参数或者BaseModel的Config都可以实现未api文档增加样例,如果没有上述设置了样例但是设置了默认值,也可实现样例。
数据类型
除了标准库里面的int, str, float, bool,还支持其他的数据类型。
UUID(from uuid import UUID)形如"3fa85f64-57174562-b3fc-2c963f66afa6", 在调用的时候,中间的分隔符"-"可以去掉一个或多个,但是在接口识别的时候,仍会有分隔符"-"。
datetime(from datetime import datetime): 符合ISO8601格式的时间字符串,例如”2020-01-01 12:00:00“
date(from datetime import date): 符合ISO8601格式的日期字符串,例如”2020-01-01“
time(from datetime import time): 符合ISO8601格式的时间字符串,例如”12:00:00“
timedelta(from datetime import timedelta):相当于float类型的秒数
frozenset: 在请求端是以数组的形式存在,在响应端和Set集合是一样,但是frozenset不允许进行集合的增减,是一个只读集合,还存在一个问题:如果设置了frozenset之后,redoc和swagger都会抛出异常,无法使用。我的解决方案是直接修改源码,在pydantic/schema.py中,为field_class_to_schema这个元组增加frozenset元素
(frozenset, {'type': 'array', 'items': {}, 'uniqueItems': True}),
bytes:接受str类型,转化成bytes类型,‘123’ -> b'123'
Decimal: 和float相似。