FastAPI: API 文档与 OpenAPI 定制 — 打造专业 API 文档
最后更新:2026-08-26
API 文档就像产品说明书——没有它,客户(开发者)不会用你的产品;写得不好,客户会用脚投票。自动生成文档是 FastAPI 的杀手锏,但默认配置只是起点,定制才是专业。
1. 你将学到
- Swagger UI 与 ReDoc 配置:
swagger_ui_parameters、自定义 JS/CSS - OpenAPI Schema 定制:
openapi_route、自定义generate_unique_id_function description/summary/tags/deprecated最佳实践- 示例值与响应模板:
OpenApiResponse+json_schema_extra - Alice 场景:PriceTracker 的专业 SaaS API 文档
2. Alice 的真实故事
(1) 痛点:默认文档不够专业
Alice 的 PriceTracker API 文档是 FastAPI 默认的 Swagger UI,所有端点混在一起没有分组,Bob 找不到需要的端点。更糟的是,文档没有示例请求,Bob 不知道 currency 字段该填什么值,请求体和响应体没有版本区分,新端点和废弃端点混在一起。
(2) OpenAPI 定制的解法
FastAPI 允许深度定制 OpenAPI 文档:tags 分组、示例值、废弃标记、自定义 Schema——让 API 文档从"能看"变成"好用"。
(3) 收益
Bob 打开文档即可按标签(Products/Prices/Auth)快速定位端点,示例值让请求不再猜填,废弃端点灰色标记不会误用,文档质量从"内部参考"升级为"对外发布级"。
3. Swagger UI 与 ReDoc 配置
(1) OpenAPI 生成流程
flowchart LR
A[FastAPI Routes] --> B[Pydantic Models]
B --> C[OpenAPI 3.1 Schema]
C --> D[Swagger UI /docs]
C --> E[ReDoc /redoc]
C --> F[Raw JSON /openapi.json]
▶ 示例:FastAPI 应用级文档配置
PYTHON
from fastapi import FastAPI
app = FastAPI(
title="PriceTracker API",
description="""
## PriceTracker SaaS API
E-commerce price tracking service for monitoring million-level product prices.
### Authentication
All protected endpoints require a Bearer token obtained from `/auth/login`.
### Rate Limits
- Free: 100 requests/min
- Pro: 1000 requests/min
- Enterprise: unlimited
""",
version="1.0.0",
terms_of_service="https://pricetracker.example.com/terms",
contact={
"name": "PriceTracker Support",
"url": "https://pricetracker.example.com/support",
"email": "support@pricetracker.example.com",
},
license_info={
"name": "MIT License",
"url": "https://opensource.org/licenses/MIT",
},
docs_url="/docs",
redoc_url="/redoc",
openapi_url="/openapi.json",
)
输出:
TEXT
📖 仅展示
# 执行成功
▶ 示例:Swagger UI 参数定制
PYTHON
app = FastAPI(
swagger_ui_parameters={
"persistAuthorization": True, # Keep auth between page refreshes
"displayRequestDuration": True, # Show request duration
"filter": True, # Enable search filter
"syntaxHighlight.theme": "monokai", # Code highlighting theme
"defaultModelsExpandDepth": 1, # Expand models 1 level deep
"defaultModelExpandDepth": 1,
}
)
输出:
TEXT
📖 仅展示
# 执行成功
| 参数 | 默认 | 说明 |
|---|---|---|
persistAuthorization |
False | 刷新页面保留认证 |
displayRequestDuration |
False | 显示请求耗时 |
filter |
False | 启用搜索过滤 |
defaultModelsExpandDepth |
1 | 模型展开深度 |
syntaxHighlight.theme |
"agate" | 代码高亮主题 |
4. Tags 分组与 deprecated 标记
(1) Tags 分组端点
▶ 示例:定义 Tags
PYTHON
from fastapi import FastAPI, APIRouter
tags_metadata = [
{
"name": "auth",
"description": "Authentication operations. Login, register, token refresh.",
},
{
"name": "products",
"description": "Product management. CRUD operations for tracked products.",
},
{
"name": "prices",
"description": "Price data. Query, import, and track price changes.",
},
{
"name": "admin",
"description": "Admin operations. Requires admin role.",
},
]
app = FastAPI(
title="PriceTracker API",
openapi_tags=tags_metadata,
)
输出:
TEXT
📖 仅展示
# 执行成功
▶ 示例:端点分配 Tags
PYTHON
@app.post("/auth/login", tags=["auth"])
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
...
@app.get("/api/v1/products", tags=["products"])
async def list_products():
...
@app.post("/api/v1/prices", tags=["prices"])
async def create_price():
...
@app.get("/api/v1/admin/stats", tags=["admin"])
async def admin_stats():
...
输出:
TEXT
📖 仅展示
# 函数定义成功
▶ 示例:deprecated 标记废弃端点
PYTHON
@app.get(
"/api/v1/products/{product_id}/history",
tags=["prices"],
deprecated=True,
summary="[DEPRECATED] Use GET /prices?product_id={id} instead",
)
async def get_price_history_deprecated(product_id: int):
"""This endpoint is deprecated. Use the prices endpoint with product_id filter."""
...
输出:
TEXT
📖 仅展示
# 函数定义成功
5. 示例值与响应模板
(1) json_schema_extra 与 examples
▶ 示例:Pydantic 模型示例值
PYTHON
from pydantic import BaseModel, Field
class ProductCreate(BaseModel):
name: str = Field(
min_length=1, max_length=200,
description="Product display name",
examples=["Wireless Mouse", "USB-C Hub", "Mechanical Keyboard"],
)
category: str = Field(
max_length=100,
description="Product category",
examples=["electronics", "clothing", "food"],
)
base_price: float = Field(
gt=0,
description="Base price in USD",
examples=[9.99, 49.99, 199.99],
)
model_config = {
"json_schema_extra": {
"examples": [
{
"name": "Wireless Mouse",
"category": "electronics",
"base_price": 29.99,
}
]
}
}
输出:
TEXT
📖 仅展示
# 执行成功
▶ 示例:端点级响应示例
PYTHON
from fastapi import FastAPI
from fastapi.responses import JSONResponse
@app.post(
"/api/v1/products",
response_model=ProductResponse,
status_code=201,
summary="Create a new product",
description="Create a new product in the PriceTracker database.",
responses={
201: {
"description": "Product created successfully",
"content": {
"application/json": {
"example": {
"id": 1,
"name": "Wireless Mouse",
"category": "electronics",
"base_price": 29.99,
}
}
},
},
401: {"description": "Authentication required"},
403: {"description": "Insufficient permissions"},
422: {"description": "Validation error"},
},
)
async def create_product(product: ProductCreate):
...
输出:
TEXT
📖 仅展示
# 函数定义成功
6. 自定义 OpenAPI Schema
(1) generate_unique_id_function
▶ 示例:自定义端点 ID 生成
PYTHON
from fastapi import FastAPI
def custom_generate_unique_id(route):
# Format: {method}_{tag}_{path}
tags = route.tags or ["default"]
tag = tags[0]
method = route.methods.pop() if route.methods else "GET"
path = route.path.replace("/", "_").strip("_").replace("{", "").replace("}", "")
return f"{method}_{tag}_{path}"
app = FastAPI(
generate_unique_id_function=custom_generate_unique_id,
)
输出:
TEXT
📖 仅展示
# 函数定义成功
(2) 文档最佳实践对比
| 维度 | 默认 | 最佳实践 |
|---|---|---|
| 端点分组 | 无 | Tags 按功能分组 |
| 废弃端点 | 与正常端点混在一起 | deprecated=True 灰色标记 |
| 请求示例 | 无 | examples + json_schema_extra |
| 响应模板 | 仅 200 | 201/401/403/422 全覆盖 |
| 描述 | 简单函数名 | summary + description |
| 认证说明 | 无 | 文档首页说明认证方式 |
| 版本化 | 单版本 | URL 路径版本 /api/v1/ |
❓ 常见问题
Q Swagger UI 和 ReDoc 有什么区别?
A Swagger UI 交互式(可测试 API),ReDoc 阅读式(更美观)。对外文档推荐 ReDoc,内部开发用 Swagger UI。
Q 如何隐藏某些端点不在文档中显示?
A 设置
include_in_schema=False:@app.get("/internal", include_in_schema=False)。适合内部健康检查、监控端点。Q OpenAPI 版本用 3.0 还是 3.1?
A FastAPI 默认生成 OpenAPI 3.1(支持 JSON Schema 最新特性)。如需兼容旧工具,可在自定义 openapi 函数中降级。
Q 如何给文档加自定义 CSS/JS?
A 通过
swagger_ui_parameters 传 CSS URL,或用 get_swagger_ui_html 完全自定义 HTML。Q 示例值和默认值有什么区别?
A examples 是文档展示用,不影响校验;default 是实际默认值,影响行为。两者都应该设置。
Q 多版本 API 的文档如何组织?
A 每个版本用独立的
APIRouter(prefix="/api/v1"),在 Tags 中区分版本。或为每个版本创建独立的 FastAPI 子应用。📖 小节
- FastAPI 自动生成 OpenAPI 3.1 文档,Swagger UI 交互式测试,ReDoc 美观阅读
openapi_tags按功能分组端点,deprecated=True标记废弃端点Field(examples=[...])和json_schema_extra为模型添加示例值responses={status: {description, content}}为端点定义多状态码响应模板- 自定义
generate_unique_id_function控制 OpenAPI 操作 ID 命名格式
📝 作业
- 基础题(难度⭐):为 PriceTracker 配置 FastAPI 应用级文档——标题、描述、版本号、联系方式,添加
persistAuthorization=True让 Swagger UI 保留认证状态。提示:FastAPI(title=..., swagger_ui_parameters={...}) - 进阶题(难度⭐⭐):定义 4 个 Tags(auth/products/prices/admin),为每个端点分配正确的 Tag,标记废弃端点
deprecated=True,验证 Swagger UI 中端点按标签分组。提示:openapi_tags=[...]+tags=["products"] - 挑战题(难度⭐⭐⭐):为 ProductCreate 添加
json_schema_extra完整示例,为 POST /products 端点添加 201/401/403/422 多状态码响应模板含示例内容,实现自定义generate_unique_id_function。提示:responses={201: {"content": {...}}}+generate_unique_id_function
---|