fastapi之响应模型(上)

265 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第18天,点击查看活动详情

响应模型response_model

  • fastapi支持用户响应指定的数据模型,在路径操作装饰器中使用参数response_model
  • 比如下面这个例子中,我们使用:response_model=Item,则响应的数据的类型必须是Item,否则报错。
 from typing import List, Union
 ​
 from fastapi import FastAPI
 from pydantic import BaseModel
 ​
 app = FastAPI()
 ​
 ​
 class Item(BaseModel):
     name: str
     description: Union[str, None] = None
     price: float
     tax: Union[float, None] = None
     tags: List[str] = []
 ​
 ​
 @app.post("/items/", response_model=Item)
 async def create_item(item: Item):
     return item
  • 一般response_model用来做数据过滤,比如注册接口接收用户输入的密码,但是响应数据不能包含密码,
  • 定义UserIn用来接收请求体数据,定义UserOut用来做响应数据;区别是后者比前者少了密码字段。
  • 此时,在路径参数内即使返回的userUserIn类型,但因为设置了response_model=UserOut所以响应数据中没有密码。
 from typing import Union
 ​
 from fastapi import FastAPI
 from pydantic import BaseModel
 ​
 app = FastAPI()
 ​
 ​
 class UserIn(BaseModel):
     username: str
     password: str
     email: str
     full_name: Union[str, None] = None
 ​
 ​
 class UserOut(BaseModel):
     username: str
     email: str
     full_name: Union[str, None] = None
 ​
 ​
 @app.post("/user/", response_model=UserOut)
 async def create_user(user: UserIn):
     return user
  • 此时在openapi中也可以看到相应的UI提示。

response_model_exclude_unset

  • 除了response_model,还可以通过response_model_exclude_unset来过滤没有赋值的字段,即如果模型类中某个字段有默认值,响应数据这个字段没有赋值时,则响应时会把这个字段过滤掉。
 from typing import List, Union
 ​
 from fastapi import FastAPI
 from pydantic import BaseModel
 ​
 app = FastAPI()
 ​
 ​
 class Item(BaseModel):
     name: str
     description: Union[str, None] = 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": []},
 }
 ​
 ​
 @app.get("/items/{item_id}", response_model=Item, response_model_exclude_unset=True)
 async def read_item(item_id: str):
     return items[item_id]
  • 上面例子中:

    • description 有默认值None
    • tax有默认值10.5
    • tags有默认值[]
  • 如果item_id=foo,则三个有默认数据的字典每过滤掉,所以响应数据为:

 {
     "name": "Foo",
     "price": 50.2
 }
  • 如果item_id=bar, 因为前4个字段都有赋值,最后一个是有默认值的字段,所以返回值中只过滤掉最后一个。
  • 如果item_id=baz, 因为每个字段都有赋值(即使赋值和默认值一样),此时所有字段都不会被过滤。

补充:response_model_exclude_unset=True等价于item.dict(exclude_unset=True)

response_model_exclude_defaults

  • 过滤那些和默认值一样的字段,response_model_exclude_defaults=True
  • 等价于:item.dict(exclude_defaults=True)

response_model_exclude_none

  • 过滤哪些是None的字段,response_model_exclude_none=Trye
  • 等价于:item.dict(exclude_none=True)

response_model_include

  • 被包含的字段被保留,其他的被过滤,接收一个Set,如:response_model_include={"name", "description"}
  • 如果你忘记使用Set,使用列表或者元组,此时fastapi会帮忙自动转换。
  • 等价于:item.dict(include={"name", "description"})

response_model_exclude

  • 被排除的字段过滤,其他字段保留,接收一个Set,如:response_model_exclude={"tax"}
  • 如果你忘记使用Set,使用列表或者元组,此时fastapi会帮忙自动转换。
  • 等价于:item.dict(exclude={"tax"})