路径操作高级配置¶
OpenAPI operationId¶
警告
如果你不是 OpenAPI 的“专家”,通常不需要用到此功能。
你可以通过 operation_id 参数为路径操作设置要在 OpenAPI 中使用的 operationId。
你需要确保每个操作的 ID 都是唯一的。
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/", operation_id="some_specific_id_you_define")
async def read_items():
return [{"item_id": "Foo"}]
使用路径操作函数名作为 operationId¶
如果你想使用 API 的函数名作为 operationId,可以遍历所有路径操作,并使用 APIRoute.name 重写每个路径操作的 operation_id。
你应该在添加完所有路径操作之后执行此操作。
from fastapi import FastAPI
from fastapi.routing import APIRoute
app = FastAPI()
@app.get("/items/")
async def read_items():
return [{"item_id": "Foo"}]
def use_route_names_as_operation_ids(app: FastAPI) -> None:
"""
Simplify operation IDs so that generated API clients have simpler function
names.
Should be called only after all routes have been added.
"""
for route in app.routes:
if isinstance(route, APIRoute):
route.operation_id = route.name # in this case, 'read_items'
use_route_names_as_operation_ids(app)
提示
如果你手动调用了 app.openapi(),则应在此之前更新 operationId。
警告
如果这样做,你必须确保每个路径操作函数都有一个唯一的名称。
即使它们位于不同的模块(Python 文件)中也是如此。
从 OpenAPI 中排除¶
若要从生成的 OpenAPI 模式(以及自动文档系统)中排除某个路径操作,请将参数 include_in_schema 设置为 False。
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/", include_in_schema=False)
async def read_items():
return [{"item_id": "Foo"}]
来自文档字符串的高级描述¶
你可以限制 OpenAPI 使用路径操作函数文档字符串(docstring)的行数。
添加 \f(转义的“换页”字符)会使 FastAPI 在该位置截断用于 OpenAPI 的输出。
它不会显示在文档中,但其他工具(如 Sphinx)将能够使用剩余部分。
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
tags: set[str] = set()
@app.post("/items/", summary="Create an item")
async def create_item(item: Item) -> Item:
"""
Create an item with all the information:
- **name**: each item must have a name
- **description**: a long description
- **price**: required
- **tax**: if the item doesn't have tax, you can omit this
- **tags**: a set of unique tag strings for this item
\f
:param item: User input.
"""
return item
额外响应¶
你可能已经了解了如何为路径操作声明 response_model 和 status_code。
这定义了关于路径操作主要响应的元数据。
你还可以声明带有模型、状态码等的额外响应。
本文档中有一个专门的章节讲述该内容,你可以在OpenAPI 中的额外响应阅读它。
OpenAPI 扩展信息 (Extra)¶
当你在应用程序中声明路径操作时,FastAPI 会自动生成相关的元数据,并将其包含在 OpenAPI 模式中。
技术细节
在 OpenAPI 规范中,它被称为 操作对象 (Operation Object)。
它包含了关于路径操作的所有信息,并用于生成自动文档。
它包括 tags(标签)、parameters(参数)、requestBody(请求体)、responses(响应)等。
这个特定于路径操作的 OpenAPI 模式通常由 FastAPI 自动生成,但你也可以对其进行扩展。
你可以使用 openapi_extra 参数来扩展路径操作的 OpenAPI 模式。
OpenAPI 扩展 (Extensions)¶
openapi_extra 很有用,例如用于声明 OpenAPI 扩展。
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/", openapi_extra={"x-aperture-labs-portal": "blue"})
async def read_items():
return [{"item_id": "portal-gun"}]
如果你打开自动 API 文档,你的扩展信息将显示在特定路径操作的底部。

如果你查看生成的 OpenAPI(API 中的 /openapi.json),也会看到你的扩展作为特定路径操作的一部分。
{
"openapi": "3.1.0",
"info": {
"title": "FastAPI",
"version": "0.1.0"
},
"paths": {
"/items/": {
"get": {
"summary": "Read Items",
"operationId": "read_items_items__get",
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
"schema": {}
}
}
}
},
"x-aperture-labs-portal": "blue"
}
}
}
}
自定义 OpenAPI 路径操作模式¶
openapi_extra 中的字典将与自动生成的路径操作 OpenAPI 模式进行深度合并。
因此,你可以向自动生成的模式中添加额外数据。
例如,你可能决定用自己的代码读取并验证请求,而不使用 FastAPI 配合 Pydantic 的自动特性,但你仍然希望在 OpenAPI 模式中定义该请求。
你可以通过 openapi_extra 来实现这一点。
from fastapi import FastAPI, Request
app = FastAPI()
def magic_data_reader(raw_body: bytes):
return {
"size": len(raw_body),
"content": {
"name": "Maaaagic",
"price": 42,
"description": "Just kiddin', no magic here. ✨",
},
}
@app.post(
"/items/",
openapi_extra={
"requestBody": {
"content": {
"application/json": {
"schema": {
"required": ["name", "price"],
"type": "object",
"properties": {
"name": {"type": "string"},
"price": {"type": "number"},
"description": {"type": "string"},
},
}
}
},
"required": True,
},
},
)
async def create_item(request: Request):
raw_body = await request.body()
data = magic_data_reader(raw_body)
return data
在这个示例中,我们没有声明任何 Pydantic 模型。实际上,请求体甚至没有被解析为 JSON,而是直接作为 bytes 读取,函数 magic_data_reader() 将负责以某种方式进行解析。
尽管如此,我们仍然可以为请求体声明预期的模式。
自定义 OpenAPI 内容类型¶
利用同样的技巧,你可以使用 Pydantic 模型来定义 JSON Schema,并将其包含在路径操作的自定义 OpenAPI 模式部分中。
即使请求中的数据类型不是 JSON,你也可以这样做。
例如,在这个应用中,我们没有使用 FastAPI 集成的从 Pydantic 模型提取 JSON Schema 的功能,也没有使用 JSON 的自动验证。实际上,我们将请求内容类型声明为 YAML,而不是 JSON。
import yaml
from fastapi import FastAPI, HTTPException, Request
from pydantic import BaseModel, ValidationError
app = FastAPI()
class Item(BaseModel):
name: str
tags: list[str]
@app.post(
"/items/",
openapi_extra={
"requestBody": {
"content": {"application/x-yaml": {"schema": Item.model_json_schema()}},
"required": True,
},
},
)
async def create_item(request: Request):
raw_body = await request.body()
try:
data = yaml.safe_load(raw_body)
except yaml.YAMLError:
raise HTTPException(status_code=422, detail="Invalid YAML")
try:
item = Item.model_validate(data)
except ValidationError as e:
raise HTTPException(status_code=422, detail=e.errors(include_url=False))
return item
尽管如此,虽然我们没有使用默认的集成功能,但我们仍然使用 Pydantic 模型来手动生成我们希望以 YAML 接收的数据的 JSON Schema。
然后我们直接使用请求,并将请求体提取为 bytes。这意味着 FastAPI 甚至不会尝试将请求负载解析为 JSON。
接着在我们的代码中,我们直接解析该 YAML 内容,并再次使用同一个 Pydantic 模型来验证 YAML 内容。
import yaml
from fastapi import FastAPI, HTTPException, Request
from pydantic import BaseModel, ValidationError
app = FastAPI()
class Item(BaseModel):
name: str
tags: list[str]
@app.post(
"/items/",
openapi_extra={
"requestBody": {
"content": {"application/x-yaml": {"schema": Item.model_json_schema()}},
"required": True,
},
},
)
async def create_item(request: Request):
raw_body = await request.body()
try:
data = yaml.safe_load(raw_body)
except yaml.YAMLError:
raise HTTPException(status_code=422, detail="Invalid YAML")
try:
item = Item.model_validate(data)
except ValidationError as e:
raise HTTPException(status_code=422, detail=e.errors(include_url=False))
return item
提示
在这里我们复用了同一个 Pydantic 模型。
但同样地,我们也可以通过其他方式进行验证。