路径操作高级配置¶
OpenAPI operationId¶
警告
如果您不是 OpenAPI 的“专家”,您可能不需要此功能。
您可以使用参数 operation_id
来设置您的 路径操作 中使用的 OpenAPI operationId
。
您必须确保它对每个操作都是唯一的。
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 的行数。
添加 \f
(一个转义的“换页”字符)将导致 FastAPI 在此处截断用于 OpenAPI 的输出。
它不会显示在文档中,但其他工具(例如 Sphinx)将能够使用其余部分。
from typing import Set, 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: Set[str] = set()
@app.post("/items/", response_model=Item, summary="Create an item")
async def create_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 规范中,它被称为 操作对象。
它包含有关 路径操作 的所有信息,并用于生成自动文档。
它包括 tags
、parameters
、requestBody
、responses
等。
这个 路径操作 特定的 OpenAPI 模式通常由 FastAPI 自动生成,但您也可以对其进行扩展。
您可以使用参数 openapi_extra
来扩展 路径操作 的 OpenAPI 模式。
OpenAPI 扩展¶
这个 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 模式,然后将其包含在 路径操作 的自定义 OpenAPI 模式部分中。
即使请求中的数据类型不是 JSON,您也可以这样做。
例如,在此应用程序中,我们不使用 FastAPI 的集成功能从 Pydantic 模型中提取 JSON 模式,也不使用 JSON 的自动验证。事实上,我们声明请求内容类型为 YAML,而不是 JSON
from typing import List
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
from typing import List
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.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.parse_obj(data)
except ValidationError as e:
raise HTTPException(status_code=422, detail=e.errors())
return item
信息
在 Pydantic 版本 1 中,获取模型 JSON 模式的方法是 Item.schema()
,而在 Pydantic 版本 2 中,该方法名为 Item.model_json_schema()
。
尽管如此,虽然我们没有使用默认的集成功能,我们仍然使用 Pydantic 模型手动生成 JSON 模式,用于我们希望以 YAML 格式接收的数据。
然后我们直接使用请求,并将请求体提取为 bytes
。这意味着 FastAPI 甚至不会尝试将请求负载解析为 JSON。
然后在我们的代码中,我们直接解析 YAML 内容,然后我们再次使用相同的 Pydantic 模型来验证 YAML 内容
from typing import List
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
from typing import List
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.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.parse_obj(data)
except ValidationError as e:
raise HTTPException(status_code=422, detail=e.errors())
return item
信息
在 Pydantic 版本 1 中,解析和验证对象的方法是 Item.parse_obj()
,而在 Pydantic 版本 2 中,该方法名为 Item.model_validate()
。
提示
在这里,我们重用了相同的 Pydantic 模型。
但是,以同样的方式,我们也可以通过其他方式验证它。