目錄
01-6. 自動生成 API 文件
⏱️ 閱讀時間: 10 分鐘 🎯 難度: ⭐ (入門)
🤔 一句話解釋
FastAPI 自動根據你的程式碼生成互動式 API 文件,不需要額外撰寫!
📚 兩種內建文件介面
FastAPI 內建兩種 API 文件介面:
Swagger UI
訪問: http://localhost:8000/docs特色:
- ✅ 互動式測試(直接在瀏覽器發送請求)
- ✅ 清楚的請求/回應格式
- ✅ 支援認證測試
- ✅ 業界標準
ReDoc
訪問: http://localhost:8000/redoc特色:
- ✅ 更美觀的閱讀介面
- ✅ 適合作為對外文件
- ✅ 支援搜尋
- ✅ 支援下載 OpenAPI 規格
🎨 自訂 API 資訊
基本設定
from fastapi import FastAPI
app = FastAPI(
title="我的超棒 API",
description="""
## 🚀 API 說明
這是一個功能強大的 API,提供以下功能:
* **使用者管理** - 註冊、登入、個人資料
* **商品管理** - 新增、編輯、刪除商品
* **訂單處理** - 建立訂單、追蹤狀態
### 認證方式
使用 JWT Bearer Token 進行認證。
""",
version="1.0.0",
terms_of_service="https://example.com/terms/",
contact={
"name": "API Support",
"url": "https://example.com/support",
"email": "support@example.com",
},
license_info={
"name": "MIT License",
"url": "https://opensource.org/licenses/MIT",
},
)自訂文件路徑
app = FastAPI(
docs_url="/api/docs", # Swagger UI 路徑
redoc_url="/api/redoc", # ReDoc 路徑
openapi_url="/api/openapi.json", # OpenAPI schema 路徑
)
# 或者完全禁用(私有 API)
app = FastAPI(
docs_url=None,
redoc_url=None,
openapi_url=None,
)🏷️ 使用 Tags 組織 API
基本用法
from fastapi import FastAPI
app = FastAPI()
# 使用 tags 分類 API
@app.get("/users/", tags=["使用者"])
async def list_users():
"""列出所有使用者"""
return []
@app.post("/users/", tags=["使用者"])
async def create_user():
"""建立新使用者"""
return {}
@app.get("/items/", tags=["商品"])
async def list_items():
"""列出所有商品"""
return []
@app.post("/items/", tags=["商品"])
async def create_item():
"""建立新商品"""
return {}定義 Tags 詳細資訊
from fastapi import FastAPI
tags_metadata = [
{
"name": "使用者",
"description": "使用者相關操作,包含註冊、登入、個人資料管理",
},
{
"name": "商品",
"description": "商品相關操作",
"externalDocs": {
"description": "商品 API 詳細說明",
"url": "https://example.com/docs/items",
},
},
{
"name": "訂單",
"description": "訂單相關操作",
},
]
app = FastAPI(
title="電商 API",
openapi_tags=tags_metadata
)📝 撰寫好的 API 文件
Docstring 會自動出現在文件中
from fastapi import FastAPI, Path, Query
from pydantic import BaseModel, Field
app = FastAPI()
class UserCreate(BaseModel):
"""建立使用者的請求模型"""
name: str = Field(..., description="使用者名稱", example="John Doe")
email: str = Field(..., description="電子郵件", example="john@example.com")
age: int = Field(..., ge=0, le=150, description="年齡", example=25)
class UserResponse(BaseModel):
"""使用者回應模型"""
id: int = Field(..., description="使用者 ID", example=1)
name: str = Field(..., description="使用者名稱", example="John Doe")
email: str = Field(..., description="電子郵件", example="john@example.com")
@app.post(
"/users/",
response_model=UserResponse,
tags=["使用者"],
summary="建立新使用者",
response_description="成功建立的使用者資訊"
)
async def create_user(user: UserCreate):
"""
建立新使用者帳號
- **name**: 使用者的顯示名稱,長度 1-100 字元
- **email**: 唯一的電子郵件地址,會用於登入
- **age**: 使用者年齡,必須介於 0-150 之間
成功建立後會回傳使用者資訊(不包含密碼)。
### 注意事項
1. Email 必須是唯一的
2. 建立後會發送驗證郵件
"""
return {"id": 1, "name": user.name, "email": user.email}路徑參數和查詢參數的文件
from fastapi import FastAPI, Path, Query
from typing import Optional
from enum import Enum
app = FastAPI()
class SortOrder(str, Enum):
asc = "asc"
desc = "desc"
@app.get("/users/{user_id}", tags=["使用者"])
async def get_user(
user_id: int = Path(
...,
title="使用者 ID",
description="要查詢的使用者 ID",
ge=1,
example=123
),
include_posts: bool = Query(
False,
description="是否包含使用者的文章"
),
include_comments: bool = Query(
False,
description="是否包含使用者的評論"
)
):
"""
根據 ID 獲取使用者資訊
可選擇是否包含相關的文章和評論資料。
"""
return {"user_id": user_id}
@app.get("/users/", tags=["使用者"])
async def list_users(
skip: int = Query(0, ge=0, description="跳過的數量"),
limit: int = Query(10, ge=1, le=100, description="返回的數量"),
search: Optional[str] = Query(
None,
min_length=2,
max_length=50,
description="搜尋關鍵字(姓名或 email)"
),
sort_by: str = Query("created_at", description="排序欄位"),
order: SortOrder = Query(SortOrder.desc, description="排序方向")
):
"""
列出使用者清單
支援分頁、搜尋和排序功能。
"""
return []🎯 定義回應範例
方法 1:在 Field 中使用 example
from pydantic import BaseModel, Field
class Item(BaseModel):
name: str = Field(..., example="iPhone 15")
price: float = Field(..., example=999.99)
description: str = Field(None, example="最新款智慧型手機")方法 2:使用 model_config
from pydantic import BaseModel, ConfigDict
class Item(BaseModel):
name: str
price: float
description: str = None
model_config = ConfigDict(
json_schema_extra={
"example": {
"name": "iPhone 15",
"price": 999.99,
"description": "最新款智慧型手機"
}
}
)方法 3:在路由中定義多個範例
from fastapi import FastAPI, Body
app = FastAPI()
@app.post("/items/")
async def create_item(
item: Item = Body(
...,
openapi_examples={
"normal": {
"summary": "一般商品",
"description": "一般商品的範例",
"value": {
"name": "筆記本",
"price": 99.9,
"description": "A5 大小"
}
},
"expensive": {
"summary": "高價商品",
"description": "高價商品的範例",
"value": {
"name": "MacBook Pro",
"price": 59900.0,
"description": "16 吋 M3 Max"
}
}
}
)
):
return item📊 定義多種回應
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
class Message(BaseModel):
message: str
@app.get(
"/items/{item_id}",
response_model=Item,
responses={
200: {
"description": "成功獲取商品",
"content": {
"application/json": {
"example": {"name": "iPhone", "price": 999.99}
}
}
},
404: {
"description": "商品不存在",
"model": Message,
"content": {
"application/json": {
"example": {"message": "商品不存在"}
}
}
},
422: {
"description": "驗證錯誤"
}
}
)
async def get_item(item_id: int):
if item_id == 0:
raise HTTPException(status_code=404, detail="商品不存在")
return {"name": "Item", "price": 10.0}🔐 在文件中添加認證
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
app = FastAPI()
security = HTTPBearer()
@app.get("/protected", tags=["受保護的端點"])
async def protected_route(
credentials: HTTPAuthorizationCredentials = Depends(security)
):
"""
這是一個需要認證的端點
需要在 Header 中提供 Bearer Token:
```
Authorization: Bearer <your_token>
```
"""
return {"token": credentials.credentials}Swagger UI 會自動顯示「Authorize」按鈕!
📤 匯出 OpenAPI 規格
import json
from fastapi import FastAPI
from fastapi.openapi.utils import get_openapi
app = FastAPI()
@app.get("/items/")
async def list_items():
return []
# 獲取 OpenAPI schema
def custom_openapi():
if app.openapi_schema:
return app.openapi_schema
openapi_schema = get_openapi(
title="自訂 API",
version="1.0.0",
description="這是自訂的 API 描述",
routes=app.routes,
)
# 可以在這裡自訂 schema
openapi_schema["info"]["x-logo"] = {
"url": "https://example.com/logo.png"
}
app.openapi_schema = openapi_schema
return app.openapi_schema
app.openapi = custom_openapi
# 匯出為 JSON 檔案
if __name__ == "__main__":
with open("openapi.json", "w") as f:
json.dump(app.openapi(), f, indent=2)✅ 重點總結
API 文件最佳實踐
# 1. 設定 API 基本資訊
app = FastAPI(
title="我的 API",
description="詳細說明...",
version="1.0.0"
)
# 2. 使用 Tags 分類
@app.get("/users", tags=["使用者"])
# 3. 撰寫清楚的 docstring
async def create_user(user: UserCreate):
"""
建立新使用者
- **name**: 使用者名稱
- **email**: 電子郵件
"""
# 4. 在 Pydantic 模型使用 Field
class User(BaseModel):
name: str = Field(..., description="名稱", example="John")
# 5. 定義多種回應狀態
@app.get("/items/{id}", responses={404: {"model": ErrorResponse}})文件網址
| 網址 | 說明 |
|---|---|
/docs | Swagger UI(互動式測試) |
/redoc | ReDoc(閱讀友善) |
/openapi.json | OpenAPI 規格(JSON) |
🎤 面試這樣答
Q: FastAPI 如何自動生成 API 文件?
答案:
FastAPI 會自動根據程式碼中的 Type Hints、Pydantic 模型和 Docstring 生成 OpenAPI 規格(也叫 Swagger 規格)。
這包括:
- 路由資訊(路徑、方法)
- 參數定義(路徑參數、查詢參數、請求體)
- 回應格式(從 response_model 推斷)
- 驗證規則(從 Pydantic 的 Field 推斷)
然後內建的 Swagger UI 和 ReDoc 會渲染這個規格,提供互動式文件。
🤓 小測驗
Swagger UI 的預設路徑是什麼?
如何在文件中將 API 分組?
Pydantic 模型中如何添加欄位說明?
上一篇: 01-5. 狀態碼與錯誤處理 下一篇: 01-7. 專案結構最佳實踐
最後更新:2025-12-17