fastAPI(5)--响应模型 response model

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是“装饰”方法的参数(getpost等)。不像所有参数和主体一样,具有路径操作功能

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}

 

上一篇:FastAPI 学习之路(三十五)项目结构优化


下一篇:FastAPI 学习之路(四十一)如何打断点调试我们的程序