1.
可以response_model
在任何路径操作中使用参数声明用于响应的模型:
@app.get()
@app.post()
@app.put()
@app.delete()
#!/usr/bin/env python
# encoding: utf-8
from fastapi import FastAPI
from pydantic import BaseModel
from typing import Optional, List
import uvicorn
app = FastAPI()
class Item(BaseModel):
name: str
desc: Optional[str] = None
price: float
tax: Optional[float] = None
tags: List[str] = []
@app.get('/items/', response_model=Item)
async def create_item(item: Item):
return item
if __name__ == '__main__':
uvicorn.run(app= app, host='127.0.0.1', port=8000)
注意,response_model
是“装饰”方法的参数(get
,post
等)。不像所有参数和主体一样,具有路径操作功能。
FastAPI将使用它response_model
来:
- 将输出数据转换为其类型声明。
- 验证数据。
- 在OpenAPI path操作中,为响应添加一个JSON模式。
- 将由自动文档系统使用。
但最重要的是:
- 将输出数据限制为模型的数据。我们将在下面看到其重要性。
2. 输入输出模型
#!/usr/bin/env python
# encoding: utf-8
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
from typing import Optional
import uvicorn
app = FastAPI()
class UserIn(BaseModel):
username: str
password: str
email: EmailStr
full_name: Optional[str] = None
class UserOut(BaseModel):
username: str
email: EmailStr
full_name: Optional[str] = None
@app.get('/items/', response_model=UserOut)
async def create_item(*, user: UserIn):
return user
if __name__ == '__main__':
uvicorn.run(app= app, host='127.0.0.1', port=8000)
EmailStr 安装方式: pip install pydantic[email]
如上所示,虽然路径操作函数返回的结果是user(包含了password),但我们声明的Response模型是UserOut(不包含password)。
FastAPI会过滤掉所有不在输出模型中的数据,因此最终的输出结果里并没有password
运行后结果:
{
"username": "string",
"email": "user@example.com",
"full_name": "string"
}
3. 响应模型参数
#!/usr/bin/env python
# encoding: utf-8
import uvicorn
from typing import List
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str = None
price: float
tax: float = 10.5
tags: List[str] = []
items = {
"foo": {"name": "Foo", "price": 50.2},
"bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
"baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
}
# response_model_exclude_unset=True 默认值将不包括在响应中,仅包含实际设置的值
@app.get("/items/{item_id}", response_model=Item, response_model_exclude_unset=True)
async def read_item(item_id: str):
return items[item_id]
# response_model_exclude 排除‘tax’
@app.get('/items/{item_id}/public', response_model=Item, response_model_exclude={'tax'})
async def read_item_public_data(item_id: str):
return items[item_id]
# response_model_include 为只返回这个list里的参数
@app.get(
"/items/{item_id}/name",
response_model=Item,
response_model_include={"name", "description", 'tax'},
)
async def read_item_name(item_id: str):
return items[item_id]
if __name__ == '__main__':
uvicorn.run(app= app, host='127.0.0.1', port=8000)
有时候只想返回被真正设置过的数据,而忽略其他未被设置过的或者缺省数据。可以用参数response_model_exclude_unset来实现这个目的。
# 访问:
http://127.0.0.1:8000/items/foo
# 返回结果:
{
"name": "Foo",
"price": 50.2
}
# 访问:
http://127.0.0.1:8000/items/bar/public
# 返回结果:
{
"name": "Bar",
"description": "The bartenders",
"price": 62,
"tags": []
}
# 访问:
http://127.0.0.1:8000/items/foo/name
# 返回结果:
{
"name": "Foo",
"description": null,
"tax": 10.5
}
4. 列表模型
from typing import List
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str
items = [
{"name": "Foo", "description": "There comes my hero"},
{"name": "Red", "description": "It's my aeroplane"},
]
@app.get("/items/", response_model=List[Item])
async def read_items():
return items
5. Response联合模型
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class BaseItem(BaseModel):
description: str
type: str
class CarItem(BaseItem):
type = "car"
class PlaneItem(BaseItem):
type = "plane"
size: int
items = {
"item1": {"description": "All my friends drive a low rider", "type": "car"},
"item2": {
"description": "Music is my aeroplane, it's my aeroplane",
"type": "plane",
"size": 5,
},
}
@app.get("/items/{item_id}", response_model=Union[PlaneItem, CarItem])
async def read_item(item_id: str):
return items[item_id]
6. Response字典模型
from typing import Dict
from fastapi import FastAPI
app = FastAPI()
@app.get("/keyword-weights/", response_model=Dict[str, float])
async def read_keyword_weights():
return {"foo": 2.3, "bar": 3.4}