前面介绍了HTTP参数的查询(Query),路径(Path),请求体(Body)如何声明额外的校验和元素据。
这里再讲一下Pydantic如何声明校验和元素据。
Pydantic声明校验和元数据
使用Pydantic的Field在Pydantic模型内部声明校验和元素据。
import uvicorn
from typing import Annotated
from fastapi import Body, FastAPI # 从fastapi引入Body
from pydantic import BaseModel, Field # 从 pydantic 引入Field
import asyncio
app = FastAPI()
class Item(BaseModel): # Field在 pydantic中声明额外参数
name: str
description: str | None = Field(
default=None, title="The description of the item", max_length=300
)
price: float = Field(gt=0, description="The price must be greater than zero")
tax: float | None = None
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Annotated[Item, Body(embed=True)]):
results = {"item_id": item_id, "item": item}
return results
if __name__ == '__main__':
config = uvicorn.Config(app, host='127.0.0.1', port=8000)
server = uvicorn.Server(config)
asyncio.run(server.serve())
Pydantic定义额外信息
为JSON 模式声明额外信息,使用场景就是需要提供一些提示信息的地方,比如提供一个exmple,这里可以
class Item(BaseModel):
name: str
description: str | None = Field(
default=None, title="The description of the item", max_length=300
)
price: float = Field(gt=0, description="The price must be greater than zero")
tax: float | None = None
model_config = {
"json_schema_extra": {
"examples": [
{
"name": "Foo",
"description": "A very nice Item",
"price": 35.4,
"tax": 3.2,
}
]
}
}
在FastAPI的docs中可以看到直接给出了这个exmaple
Field的附加参数
Field,Path,Query,Body 等工厂函数,都可以为JSON模式声明额外信息。
也可以通过工厂模式传递其它的任意参数,比如example
import uvicorn
from typing import Annotated
from fastapi import Body, FastAPI
from pydantic import BaseModel, Field
app = FastAPI()
class Item(BaseModel):
name: str = Field(examples=["Foo"])
description: str | None = Field(default=None, examples=["A very nice Item"])
price: float = Field(examples=[35.4])
tax: float | None = Field(default=None, examples=[3.2])
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Annotated[Item, Body(embed=True)]):
results = {"item_id": item_id, "item": item}
return results
Body的额外参数
import uvicorn
from typing import Annotated
from fastapi import Body, FastAPI
from pydantic import BaseModel, Field
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
body_examples = {
"name": "细胞生物学",
"description": "考研书籍",
"price": 35.8,
"tax": 0.6,
}
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Annotated[Item, Body(embed=True,example=body_examples)]):
results = {"item_id": item_id, "item": item}
return results
额外数据类型
可以使用int,float外的更复杂的数据类型。
- UUID: 一种标准的 "通用唯一标识符" ,在许多数据库和系统中用作ID。 在请求和响应中将以 str 表示。
- datetime.datetime: 一个 Python datetime.datetime. 在请求和响应中将表示为 ISO 8601 格式的 str ,比如: 2008-09-15T15:53:00+05:00. datetime.date: Python datetime.date.
- 在请求和响应中将表示为 ISO 8601 格式的 str ,比如: 2008-09-15. datetime.time: 一个 Python datetime.time. 在请求和响应中将表示为 ISO 8601 格式的 str ,比如: 14:23:55.003.
- datetime.timedelta: 一个 Python datetime.timedelta. 在请求和响应中将表示为 float 代表总秒数。 Pydantic 也允许将其表示为 "ISO 8601 时间差异编码" bool
import uvicorn
from datetime import datetime, time, timedelta
from typing import Annotated
from uuid import UUID
from fastapi import Body, FastAPI
app = FastAPI()
@app.put("/items/{item_id}")
async def read_items(
item_id: UUID,
start_datetime: Annotated[datetime | None, Body()] = None,
end_datetime: Annotated[datetime | None, Body()] = None,
repeat_at: Annotated[time | None, Body()] = None,
process_after: Annotated[timedelta | None, Body()] = None,
):
start_process = start_datetime + process_after
duration = end_datetime - start_process
return {
"item_id": item_id,
"start_datetime": start_datetime,
"end_datetime": end_datetime,
"repeat_at": repeat_at,
"process_after": process_after,
"start_process": start_process,
"duration": duration,
}