使用response_model
参数,即可在以下路径参数中声明响应模型:
@app.get()
@app.put()
@app.post()
@app.delete()
from typing import List, Optional
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: Optional[float] = None
tags: List[str] = []
@app.post("/items/", response_model=Item)
async def create_item(item: Item):
return item
注意:response_model
是装饰器方法的参数,与之前的参数和请求体不同,他不是路径操作函数的参数。
response_model
接收的类型与声明Pydantic模型属性的类型相同,可以是Pydantic模型,也可以是Pydantic模型列表,例如:List[Item]
返回相同的输入数据
from typing import Optional
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
app = FastAPI()
class UserIn(BaseModel):
username: str
password: str
email: EmilStr
full_name: Optional[str] = None
@app.post("/user/", response_model=UserIn)
async def create_user(user: UserIn):
return user
使用此模型声明输入对象,并使用同一个模型声明输出对象:
from typing import Optional
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
app = FastAPI()
class UserIn(BaseModel):
username: str
password: str
email: EmailStr
full_name: Optional[str] = None
# Don't do this in production!
@app.post("/user/", response_model=UserIn)
async def create_user(user: UserIn):
return user
现在,只要在浏览器中使用密码创建用户,API就会在响应中国返回相同的密码。本例中,因为是用户本人发送密码,这种操作没什么问题,但是如果在其他路径操作中使用同一个模型,就会把用户的密码发送给每一个客户端。
添加输出模型
相对于包含明文密码的输入模型,创建不含明文密码的输出模型:
from typing import Optional
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
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.post("/user/", response_model=UserOut)
async def create_user(user: UserIn):
return user
这样,即便路径操作函数返回同样的输入用户:
from typing import Optional
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
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.post("/user/", response_model=UserOut)
async def create_user(user: UserIn):
return user
但因为response_model中声明的UserOut模型没有包含密码:
from typing import Optional
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
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.post("/user/", response_model=UserOut)
async def create_user(user: UserIn):
return user
FastAPI会过滤掉所有未在输出模型中声明的数据。
响应模型编码参数
响应模型支持默认值:
from typing import List, Optional
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: Optional[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": []},
}
@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: Optional[str] = None
的默认值是None
tax: float = 10.5
的默认值是10.5
tags: List[str] = []
的默认值是空列表:[]
但如果没有为含默认值的属性另赋新值,输出结果会省略含默认值的属性。
例如,NoSQL 数据库的模型中往往包含很多可选属性,如果输出含默认值的属性,输出的 JSON 响应会特别长,此时,可以省略只含默认值的属性。
使用 response_model_exclude_unset
参数¶
把路径操作装饰器的参数设置为 response_model_exclude_unset=True
:
from typing import List, Optional
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: Optional[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": []},
}
@app.get("/items/{item_id}", response_model=Item, response_model_exclude_unset=True)
async def read_item(item_id: str):
return items[item_id]
响应中就不会再包含未修改过默认值的属性,而是只包含设置过值的属性。
因此,向路径操作发送 ID 为 foo
的商品的请求,则(不包括默认值的)响应为:
{
"name": "Foo",
"price": 50.2
}
默认值字段有实际值的数据¶
但如果为含默认值的模型字段赋予了新值,例如 ID 为 bar
的项:
{
"name": "Bar",
"description": "The bartenders",
"price": 62,
"tax": 20.2
}
这些值就会包含在返回的响应中。
与默认值相同的数据¶
如果新的数据与默认值相同,例如 ID 为 baz
的项:
{
"name": "Baz",
"description": None,
"price": 50.2,
"tax": 10.5,
"tags": []
}
虽然 FastAPI (其实是 Pydantic)能够识别出 description
、tax
和 tags
的值与默认值相同,这些值也会显式设置(而不是取自默认值)。
因此,这些值会包含在 JSON 响应里。
response_model_include
和 response_model_exclude
¶
路径操作装饰器参数还有 response_model_include
和 response_model_exclude
。
这两个参数的值是由属性名 str
组成的 set
,用于包含(忽略其它属性)或排除(包含其它属性)集合中的属性名。
如果只有一个 Pydantic 模型,但又想从中移除某些输出数据,则可以使用这种快捷方法。
from typing import Optional
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: float = 10.5
items = {
"foo": {"name": "Foo", "price": 50.2},
"bar": {"name": "Bar", "description": "The Bar fighters", "price": 62, "tax": 20.2},
"baz": {
"name": "Baz",
"description": "There goes my baz",
"price": 50.2,
"tax": 10.5,
},
}
@app.get(
"/items/{item_id}/name",
response_model=Item,
response_model_include={"name", "description"},
)
async def read_item_name(item_id: str):
return items[item_id]
@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]
用 list
代替 set
¶
不使用 set
,而是使用 list
或 tuple
,FastAPI 可以将其转换为 set
,并仍能正常运行:
from typing import Optional
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: float = 10.5
items = {
"foo": {"name": "Foo", "price": 50.2},
"bar": {"name": "Bar", "description": "The Bar fighters", "price": 62, "tax": 20.2},
"baz": {
"name": "Baz",
"description": "There goes my baz",
"price": 50.2,
"tax": 10.5,
},
}
@app.get(
"/items/{item_id}/name",
response_model=Item,
response_model_include=["name", "description"],
)
async def read_item_name(item_id: str):
return items[item_id]
@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]
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现