はい、承知いたしました。FastAPIのAPIドキュメント自動生成機能、特にSwagger UIの使い方に焦点を当て、約5000語の詳細な記事を作成します。
FastAPIでAPIドキュメント自動生成!Swagger UIの強力な使い方を徹底解説
はじめに:なぜAPIドキュメントは重要なのか?
現代のソフトウェア開発において、API(Application Programming Interface)はシステム間の連携の要となっています。フロントエンドとバックエンド、異なるマイクロサービス間、あるいは外部パートナーとのデータ連携など、APIは多岐にわたる場面で利用されます。
しかし、どんなに優れたAPIであっても、その使い方や仕様が明確にドキュメント化されていなければ、利用者はAPIを効果的に使うことができません。むしろ、誤解や不適切な利用によって、システム全体の不具合を引き起こす可能性すらあります。
質の高いAPIドキュメントは、以下のような多くの利点をもたらします。
- 開発者間の連携促進: チーム内のバックエンド開発者、フロントエンド開発者、モバイルアプリ開発者などが共通理解を持ち、スムーズに開発を進めることができます。
- 外部利用者への情報提供: APIを公開する場合、利用者はドキュメントを見てAPIの機能、パラメータ、レスポンス、認証方法などを理解します。これはAPI普及の鍵となります。
- 保守性と可読性の向上: ドキュメントはAPIの「説明書」として機能し、将来的な機能追加や変更、あるいはバグ修正を行う際に、APIの全体像や詳細を素早く把握するのに役立ちます。
- テストの効率化: APIドキュメントは、単体テスト、結合テスト、E2Eテストなどのテストケースを作成する際の基盤となります。
しかし、手動でAPIドキュメントを作成し、それを最新の状態に保つのは非常に骨の折れる作業です。APIの仕様変更が発生するたびにドキュメントを更新する必要があり、この作業が疎かになると、ドキュメントと実際のAPIの間に乖離が生じ、「古い、間違った情報」となってしまい、かえって混乱を招きます。
ここで登場するのが、APIフレームワークによる自動ドキュメント生成機能です。フレームワークがコードからAPIの仕様を読み取り、自動的にドキュメントを生成してくれれば、開発者はドキュメント更新の手間から解放され、APIのコードそのものに集中できます。
FastAPIは、この自動ドキュメント生成において特に強力な機能を提供します。Pythonの型ヒントを最大限に活用し、OpenAPIという標準仕様に基づいたリッチなAPIドキュメントを自動生成します。そして、そのドキュメントをインタラクティブに操作できるUIとして、Swagger UIとReDocを標準で提供しているのです。
この記事では、FastAPIが自動生成するドキュメント、特に多くの開発者に利用されているSwagger UIに焦点を当て、その使い方、表示内容のカスタマイズ方法、そしてAPI開発における活用方法について、詳細かつ実践的に解説します。
1. FastAPIとは? 自動ドキュメント生成の基盤
FastAPIは、モダンで高速な(高パフォーマンスな)Webフレームワークであり、Pythonの標準的な型ヒントに基づいています。主に以下の3つの主要なコンポーネントの上に成り立っています。
- Starlette: 軽量なASGI(Asynchronous Server Gateway Interface)フレームワーク。FastAPIの基盤として、非同期処理やWebSocketなどをサポートします。
- Pydantic: Pythonの型ヒントを用いたデータバリデーションライブラリ。リクエストボディやレスポンスデータのスキーマ定義、バリデーション、シリアライゼーションを強力にサポートします。
- OpenAPI (旧Swagger) & JSON Schema: APIの仕様を記述するための標準仕様。FastAPIは、コードからこの仕様を自動的に生成します。Swagger UIやReDocは、このOpenAPI仕様を読み込んで表示するツールです。
FastAPIを選ぶ主な理由の一つが、その優れた開発者体験と、冒頭で述べた自動ドキュメント生成機能です。FastAPIは、Pythonの型ヒント、Pydanticモデル、そしてパス操作関数(@app.get, @app.postなど)の定義を読み取ることで、APIの構造を正確に把握し、OpenAPI仕様に準拠したJSONスキーマを自動的に生成します。
この自動生成されたOpenAPIスキーマ(通常 /openapi.json というパスで利用可能になります)を基にして、FastAPIはデフォルトで以下の2つのインタラクティブなAPIドキュメントUIを提供します。
- Swagger UI:
/docsというデフォルトパスで利用可能。APIの各エンドポイント、パラメータ、レスポンスなどを視覚的に確認できるだけでなく、「Try it out」機能を使って実際にAPIリクエストを送信し、レスポンスを確認することができます。 - ReDoc:
/redocというデフォルトパスで利用可能。よりリッチで読みやすい静的なドキュメント表示に特化しています。
この記事では、特に開発中にAPIの仕様確認やテストに頻繁に利用されるSwagger UIに焦点を当てて解説を進めます。
2. FastAPIプロジェクトのセットアップ
まずは、FastAPIプロジェクトの基本的なセットアップを行い、自動生成されるSwagger UIにアクセスしてみましょう。
Pythonの環境が整っていることを前提とします。仮想環境(venvなど)を使用することを強く推奨します。
“`bash
プロジェクトディレクトリ作成
mkdir my-fastapi-app
cd my-fastapi-app
仮想環境作成・有効化
python -m venv venv
source venv/bin/activate # Windowsの場合は venv\Scripts\activate
必要なライブラリのインストール
fastapi: FastAPI本体
uvicorn[standard]: ASGIサーバー (uvicorn, httptools, python-dotenv, watchfiles, websocketsなどを含む)
pip install fastapi “uvicorn[standard]”
“`
次に、シンプルなFastAPIアプリケーションを作成します。main.py というファイル名で以下のコードを記述してください。
“`python
main.py
from fastapi import FastAPI
FastAPIインスタンスを作成
app = FastAPI()
ルートエンドポイント
@app.get(“/”)
async def read_root():
“””
これはルートエンドポイントです。
簡単なウェルカムメッセージを返します。
“””
return {“message”: “Hello, World!”}
パスパラメータを含むエンドポイント
@app.get(“/items/{item_id}”)
async def read_item(item_id: int):
“””
特定のアイテム情報を取得します。
- `item_id`: 取得したいアイテムのID (整数)
"""
return {"item_id": item_id}
クエリパラメータを含むエンドポイント
@app.get(“/search/”)
async def search_items(keyword: str | None = None, limit: int = 10):
“””
アイテムをキーワードで検索します。
- `keyword`: 検索キーワード (オプション)
- `limit`: 返すアイテム数の上限 (デフォルトは10)
"""
results = []
if keyword:
# 仮の検索ロジック
results = [{"name": f"Item {i} for {keyword}"} for i in range(limit)]
else:
results = [{"name": f"Item {i}"} for i in range(limit)}]
return results
“`
このコードには、FastAPIインスタンスの作成、基本的なGETメソッドのエンドポイント定義、そしてそれぞれのパス操作関数にdocstring(三重引用符 """...""")を追加しています。このdocstringはSwagger UIの description として利用されます。
アプリケーションを実行します。プロジェクトルートディレクトリで以下のコマンドを実行してください。
bash
uvicorn main:app --reload
--reload オプションは、コードの変更を検知してサーバーを自動的に再起動するためのものです。開発中は便利です。
サーバーが起動したら、ブラウザを開き、以下のURLにアクセスしてみてください。
- APIルート:
http://127.0.0.1:8000/({"message": "Hello, World!"}が表示されるはずです) - Swagger UI:
http://127.0.0.1:8000/docs - ReDoc:
http://127.00.0.1:8000/redoc
/docs にアクセスすると、FastAPIが自動生成したSwagger UIが表示されているはずです。
3. Swagger UIの基本操作
Swagger UIの画面を開くと、定義したAPIエンドポイントがリスト表示されていることがわかります。各エンドポイントは、HTTPメソッド(GET, POSTなど)とパスで識別され、その横にはパス操作関数に記述した summary またはdocstringの最初の行が表示されます。
初期状態では、定義した3つのエンドポイントが表示されています。
GET /GET /items/{item_id}GET /search/
画面構成
Swagger UIの主な構成要素は以下の通りです。
- API情報: 画面上部に、APIのタイトル、バージョン、説明などが表示されます。これは後述するFastAPIインスタンス作成時の引数や、OpenAPIスキーマで設定できます。
- エンドポイントリスト: 定義されたAPIエンドポイントがHTTPメソッドごとに色分けされてリストされます。デフォルトではパスでグループ化されます。
- エンドポイント詳細: 各エンドポイントをクリックすると、その詳細情報が表示されます。
- Description: パス操作関数のdocstringが表示されます。
- Parameters: APIが受け付けるパスパラメータ、クエリパラメータ、ヘッダー、Cookie、リクエストボディなどが一覧表示されます。それぞれの型、説明、必須/オプションなどが示されます。
- Responses: APIが返す可能性のあるHTTPステータスコード(200, 201, 400, 404など)とその際に返されるレスポンスボディのスキーマ、説明、例などが表示されます。
- Schemas: Pydanticモデルなどで定義されたデータ構造(スキーマ)が表示されます。リクエストボディやレスポンスボディの構造を理解するのに役立ちます。
- Authorizeボタン: セキュリティスキーム(認証・認可)が定義されている場合に表示されます。APIキーやトークンを入力することで、認証が必要なAPIをSwagger UI上でテストできるようになります。
「Try it out」機能
Swagger UIの最も便利な機能の一つが、「Try it out」です。これにより、ブラウザ上から実際にAPIリクエストを送信し、そのレスポンスを確認できます。
- エンドポイントを選択: Swagger UIで、テストしたいエンドポイントをクリックして詳細を開きます。
- 「Try it out」ボタンをクリック: エンドポイント詳細の右側に表示される「Try it out」ボタンをクリックします。
- パラメータを入力: パスパラメータ、クエリパラメータ、リクエストボディなどの入力フィールドが表示されるので、テストに必要な値を入力します。
- 「Execute」ボタンをクリック: 入力後、「Execute」ボタンをクリックすると、Swagger UIがそのパラメータを使って実際のAPIエンドポイントにHTTPリクエストを送信します。
- リクエスト・レスポンスを確認: リクエストが送信されると、「Curl」コマンド相当のリクエスト内容、リクエストURL、レスポンスヘッダー、レスポンスボディ、レスポンスコードなどが表示されます。
例えば、GET /items/{item_id} エンドポイントで「Try it out」をクリックすると、item_id の入力フィールドが表示されます。ここに例えば 10 と入力して「Execute」すると、http://127.0.0.1:8000/items/10 へのGETリクエストが送信され、レスポンスとして {"item_id": 10} が表示されるはずです。
GET /search/ エンドポイントでは、keyword (string) と limit (integer) の入力フィールドが表示されます。keyword に test、limit に 5 と入力して実行すると、それに応じたレスポンスが得られます。keyword を空にして limit を 3 で実行すると、キーワード指定なしで3件のアイテムが返されるはずです。
このように、「Try it out」機能を使うことで、別途APIクライアントツール(Postman, Insomnia, curlなど)を用意することなく、ブラウザ上で手軽にAPIの動作確認や簡単なテストを行うことができます。
4. API定義のカスタマイズと強化
FastAPIの自動生成ドキュメントは、コードの記述内容(特に型ヒントとPydanticモデル)から多くの情報を取得しますが、さらに詳細な情報を追加したり、表示を整理したりするために、様々なカスタマイズが可能です。これらのカスタマイズは、より正確で分かりやすいAPIドキュメントを作成するために非常に重要です。
4.1. パス操作関数におけるカスタマイズ
@app.get(), @app.post(), @app.put(), @app.delete() などのパス操作関数には、ドキュメント表示を制御するための様々な引数が用意されています。
summary: エンドポイントリストに表示される短い要約。docstringの最初の行がない場合や、docstringよりも短い説明を表示したい場合に使います。description: エンドポイント詳細に表示される説明文。docstring全体がデフォルトで使われますが、ここで別途指定することも可能です。よりリッチな表現(Markdown記法も利用可能)を記述できます。tags: APIエンドポイントをグルーピングするためのリスト。例えば["Users"],["Items"],["Authentication"]のように指定すると、Swagger UIで指定したタグごとにエンドポイントが整理されて表示されます。response_description: レスポンスセクションに表示される説明文。デフォルトは “Successful Response” です。deprecated: APIが非推奨であるかを示す真偽値。Trueに設定すると、Swagger UI上でそのAPIが非推奨であることが視覚的に示されます。将来的に削除予定のAPIなどに設定すると、利用者に注意喚起できます。status_code: デフォルトのレスポンスステータスコードを指定します(例:status_code=201)。ドキュメント上でもデフォルトの成功レスポンスコードとして表示されます。
例:
“`python
from fastapi import FastAPI, status
app = FastAPI()
タグ、サマリー、説明、非推奨フラグ付きエンドポイント
@app.post(“/users/”, tags=[“Users”], summary=”新しいユーザーを作成”, description=”指定された情報で新しいユーザーアカウントを作成します。”, status_code=status.HTTP_201_CREATED)
async def create_user():
“””
このdocstringはdescription引数が指定されていない場合に利用されます。
ここではdescription引数を指定しているので、このdocstringはSwagger UIには表示されません。
“””
# ユーザー作成ロジック
return {“message”: “User created successfully”}
@app.get(“/old-endpoint/”, tags=[“Legacy”], deprecated=True)
async def get_old_data():
“””
このエンドポイントは非推奨です。
“””
return {“data”: “This is old data”}
“`
このように引数を活用することで、Swagger UI上での表示をより整理し、分かりやすくすることができます。
4.2. パラメータのカスタマイズ (Query, Path, Bodyなど)
FastAPIは、関数引数の型ヒントとデフォルト値に基づいて、パラメータの種類(クエリ、パス、ボディなど)、型、必須/オプションを自動的に判断します。さらに、Query, Path, Body, Form, Cookie, Header, File といったクラスを使うことで、パラメータに詳細なメタ情報(タイトル、説明、例、エイリアスなど)やバリデーション規則を追加できます。これらの情報もすべてSwagger UIに反映されます。
Query: クエリパラメータの定義に使用します。Path: パスパラメータの定義に使用します。Body: リクエストボディの定義に使用します。Form: フォームデータ (application/x-www-form-urlencodedまたはmultipart/form-data) の定義に使用します。Cookie: Cookieパラメータの定義に使用します。Header: ヘッダーパラメータの定義に使用します。File: ファイルアップロードの定義に使用します。
これらのクラスは、共通して以下の引数を持ち、ドキュメント表示に影響します。
default: パラメータのデフォルト値。省略可能なパラメータの場合に指定します。alias: パラメータの実際の名前とは異なる名前をSwagger UIで表示したい場合に指定します。例えば、Pythonの変数名として無効な名前(ハイフンを含むなど)をAPIのパラメータ名として使いたい場合に便利です。title: パラメータの短いタイトル。description: パラメータの詳細な説明文。example: パラメータの単一の例。Swagger UIの「Try it out」でデフォルトの入力値として表示されることがあります。examples: パラメータの複数の例。より複雑なケースや異なるシナリオを示すのに便利です。OpenAPI 3.0で導入された機能です。include_in_schema:Falseに設定すると、そのパラメータはOpenAPIスキーマ(したがってSwagger UI)から除外されます。内部的なパラメータなどに利用します。- バリデーション関連:
gt,ge,lt,le,min_length,max_length,regexなど。これらのバリデーション規則もSwagger UIのパラメータ説明として表示されます。
例:
“`python
from fastapi import FastAPI, Query, Path, Body
from pydantic import BaseModel, Field
app = FastAPI()
class Item(BaseModel):
name: str = Field(…, example=”Awesome Item”, description=”アイテム名”)
description: str | None = Field(None, example=”A very awesome item”, description=”アイテムの詳細説明”)
price: float = Field(…, gt=0, example=10.5, description=”価格 (0より大きい)”)
tax: float | None = Field(None, ge=0, le=10, example=1.5, description=”税金 (%)”)
class Config:
# exampleデータはBaseModel全体にも指定できる
json_schema_extra = {
"examples": [
{
"name": "Foobar",
"description": "A foo bar",
"price": 35.4,
"tax": 3.2,
},
{
"name": "Baz",
"price": 10.2,
}
]
}
パラメータにQuery, Pathを使用
@app.get(“/items/{item_id}”)
async def read_item(
item_id: int = Path(…, title=”アイテムID”, description=”取得したいアイテムのユニークなID”, example=123, gt=0),
q: str | None = Query(
None,
alias=”item-query”, # エイリアスを指定
title=”アイテム検索クエリ”,
description=”アイテムをフィルタリングするためのキーワード”,
example=”latest”,
min_length=3,
max_length=50,
deprecated=True # 非推奨のクエリパラメータ
),
# 複数の例を指定
limit: int = Query(
10,
examples={
“normal”: {“value”: 10, “description”: “通常の上限数”},
“large”: {“value”: 100, “description”: “大量取得の場合の上限数”},
}
)
):
“””
特定のアイテム情報を取得します。
パスパラメータとクエリパラメータの詳細な情報がSwagger UIに表示されます。
"""
results = {"item_id": item_id}
if q:
results.update({"q": q})
results.update({"limit": limit})
return results
リクエストボディにBodyを使用
@app.post(“/items/”)
async def create_item(
item: Item = Body(
…,
title=”新しいアイテム情報”,
description=”作成するアイテムの詳細情報”,
examples={ # Body全体にも複数の例を指定可能
“example1”: {
“summary”: “完全な例”,
“description”: “全てのフィールドを含むアイテム作成リクエストの例”,
“value”: {
“name”: “Example Item”,
“description”: “This is an example item”,
“price”: 12.99,
“tax”: 1.05
}
},
“example2”: {
“summary”: “税金なしの例”,
“description”: “税金フィールドを省略したアイテム作成リクエストの例”,
“value”: {
“name”: “Another Item”,
“price”: 25.00
}
}
}
)
):
“””
新しいアイテムを登録します。
リクエストボディのスキーマと例がSwagger UIに表示されます。
"""
# アイテム作成ロジック
return item
“`
この例では、Path, Query, Body を使って、タイトル、説明、例、エイリアス、バリデーション規則などを詳細に指定しています。これらの情報はすべてSwagger UIのパラメータセクションに正確に反映され、API利用者が各パラメータの意味、期待されるフォーマット、制約などを一目で理解できるようになります。
特に example や examples は、「Try it out」機能を使う際にデフォルトの入力値として表示されたり、例として選択できたりするため、APIの典型的な使い方を示す上で非常に有効です。
4.3. リクエストボディのスキーマ定義 (Pydantic)
FastAPIは、Pydanticモデルをリクエストボディのスキーマとして使用することを推奨しています。Pydanticモデルを定義し、それをパス操作関数の引数に型ヒントとして指定するだけで、FastAPIは自動的にそのPydanticモデルのJSONスキーマを生成し、Swagger UIの「Schemas」セクションや、リクエストボディが必要なエンドポイントの詳細に表示してくれます。
Pydanticモデル内の各フィールドに Field を使用することで、そのフィールドのタイトル、説明、例、バリデーション規則などを定義できます。これらはすべてSwagger UIのスキーマ定義に反映されます。
また、Pydanticモデルの Config クラス内の json_schema_extra を使うことで、モデル全体の例をJSON形式で指定することもできます。これはSwagger UIのリクエストボディの例として表示されます。
例:
“`python
from fastapi import FastAPI, Body
from pydantic import BaseModel, Field
from typing import List
app = FastAPI()
class Product(BaseModel):
name: str = Field(…, description=”商品の名前”)
price: float = Field(…, gt=0, description=”商品の価格”)
tags: List[str] = Field([], description=”商品のタグリスト”)
class Order(BaseModel):
items: List[Product] = Field(…, description=”注文に含まれる商品のリスト”)
customer_name: str | None = Field(None, description=”顧客の名前 (オプション)”)
class Config:
json_schema_extra = {
"examples": [
{
"items": [
{"name": "Laptop", "price": 1200.0, "tags": ["electronics", "computer"]},
{"name": "Mouse", "price": 25.0, "tags": ["electronics"]}
],
"customer_name": "John Doe"
}
]
}
@app.post(“/orders/”)
async def create_order(order: Order = Body(…, description=”作成する注文の詳細”)):
“””
新しい注文を作成します。
ネストされたPydanticモデルを含むリクエストボディの例です。
"""
# 注文作成ロジック
return order
“`
この例のように、ネストされたPydanticモデルやリストを含む複雑なデータ構造も、PydanticとFastAPIを使えば簡単に定義でき、そのスキーマが正確にSwagger UIに表示されます。
4.4. レスポンスの定義
デフォルトでは、FastAPIはパス操作関数の戻り値の型ヒント(またはPydanticモデル)に基づいて、成功時(通常200または201)のレスポンスボディのスキーマをSwagger UIに表示します。これは response_model 引数を使って明示的に指定することも可能です。
さらに、エラーレスポンス(400, 404, 422, 500など)や、異なる成功レスポンス(例: 200と201)を定義し、それらのスキーマや説明、例をドキュメントに追加することができます。これには、パス操作関数の responses 引数を使用します。
responses 引数は辞書を受け取ります。キーはHTTPステータスコード(整数または文字列)、値はそのステータスコードに対するレスポンスの詳細を含む辞書です。この値の辞書には以下のキーを含めることができます。
description: そのステータスコードに対するレスポンスの説明。content: レスポンスボディの内容を記述する辞書。通常、メディアタイプ(例:"application/json")をキーとし、その値としてスキーマや例を記述します。headers: レスポンスヘッダーを記述する辞書。links: レスポンス間の関連を示すためのOpenAPI Linksオブジェクト。
例:
“`python
from fastapi import FastAPI, HTTPException, status
from pydantic import BaseModel, Field
from typing import Dict
app = FastAPI()
class User(BaseModel):
id: int = Field(…, description=”ユーザーID”)
name: str = Field(…, description=”ユーザー名”)
email: str = Field(…, description=”メールアドレス”)
エラーレスポンスのスキーマ例 (オプション)
class ErrorResponse(BaseModel):
detail: str = Field(…, example=”User not found”, description=”エラーメッセージ”)
成功時と失敗時のレスポンスを定義
@app.get(
“/users/{user_id}”,
response_model=User, # 成功時 (200) のレスポンスモデルを指定
responses={
status.HTTP_404_NOT_FOUND: {
“description”: “ユーザーが見つかりませんでした”,
“content”: {
“application/json”: {
“schema”: {“$ref”: “#/components/schemas/ErrorResponse”}, # ErrorResponseスキーマを参照
“example”: {“detail”: “User with ID 123 not found”}
}
},
# エラーレスポンスにカスタムヘッダーを含める例 (実際にはミドルウェアなどで設定することが多い)
“headers”: {
“X-Error-Code”: {
“description”: “特定のエラーコード”,
“schema”: {“type”: “string”}
}
}
},
status.HTTP_403_FORBIDDEN: {
“description”: “アクセスが拒否されました”,
“content”: {
“application/json”: {
“schema”: {“$ref”: “#/components/schemas/ErrorResponse”},
“example”: {“detail”: “Not authorized”}
}
}
}
}
)
async def read_user(user_id: int):
“””
特定のユーザー情報を取得します。
- **user_id**: 取得したいユーザーのID
存在しないユーザーIDが指定された場合は404エラーを返します。
認証されていない場合は403エラーを返す可能性があります(セキュリティ設定による)。
"""
users_db = {
1: {"id": 1, "name": "Alice", "email": "[email protected]"},
2: {"id": 2, "name": "Bob", "email": "[email protected]"},
}
if user_id not in users_db:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found")
# 実際にはここで認証チェックなどを行う
# if not authenticated:
# raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Not authorized")
return users_db[user_id]
ErrorResponseスキーマをOpenAPIスキーマに含めるために、別のエンドポイントで参照するか、
または app.openapi() を直接操作する必要がある場合があります。
この例では、responsesで参照されているため自動的に含まれます。
“`
この例では、成功時のレスポンスモデルとして User Pydanticモデルを指定し、さらに responses 引数で 404 と 403 エラーに対するレスポンスを詳細に定義しています。それぞれのレスポンスについて、説明、返されるデータ構造(ErrorResponse スキーマを参照)、そして具体的な例(example)を指定しています。これにより、Swagger UIでは各HTTPステータスコードに対する期待されるレスポンスが非常に分かりやすく表示されます。
エラーレスポンスの例を指定することで、「Try it out」機能でエラーが発生した場合に、どのような形式でレスポンスが返ってくるかをAPI利用者が事前に確認できるようになります。
4.5. Additional OpenAPI Info (FastAPIインスタンスの引数)
FastAPIインスタンスを作成する際に渡せる引数の中にも、Swagger UIを含むOpenAPIドキュメント全体に影響するものがあります。
“`python
from fastapi import FastAPI
from typing import List
API全体に適用されるタグのメタデータを定義
tags_metadata = [
{
“name”: “Users”,
“description”: “ユーザー関連の操作 (作成, 取得, 更新, 削除)”,
},
{
“name”: “Items”,
“description”: “アイテム関連の操作”,
“externalDocs”: { # 外部ドキュメントへのリンク
“description”: “アイテム関連の詳細はこちら”,
“url”: “https://example.com/items/docs”,
},
},
{
“name”: “Legacy”,
“description”: “非推奨または古いエンドポイント”,
},
# その他のタグ…
]
app = FastAPI(
title=”My Awesome API”, # APIタイトル
description=”これは、私のFastAPIによる素晴らしいAPIのドキュメントです。”, # API全体の説明
version=”1.0.0″, # APIバージョン
terms_of_service=”http://example.com/terms/”,# 利用規約へのリンク
contact={ # 連絡先情報
“name”: “API Support”,
“url”: “http://example.com/contact/”,
“email”: “[email protected]”,
},
license_info={ # ライセンス情報
“name”: “Apache 2.0”,
“url”: “https://www.apache.org/licenses/LICENSE-2.0.html”,
},
openapi_tags=tags_metadata, # タグのメタデータを指定
docs_url=”/documentation”, # Swagger UIのパスを変更
redoc_url=”/redocumentation”, # ReDocのパスを変更
openapi_url=”/api/v1/openapi.json” # OpenAPIスキーマJSONのパスを変更
# openapi_url=None, # OpenAPIスキーマの生成を無効化
# docs_url=None, # Swagger UIを無効化
# redoc_url=None, # ReDocを無効化
)
… (パス操作関数定義は省略)
“`
これらの引数を設定することで、Swagger UIのトップに表示されるAPI全体の情報(タイトル、説明、バージョン、連絡先、ライセンスなど)を充実させることができます。特に openapi_tags は、パス操作関数の tags 引数で指定したタグに対して、さらに詳細な説明や外部ドキュメントへのリンクを追加できるため、APIドキュメントのナビゲーションと理解を助けます。
また、docs_url, redoc_url, openapi_url を変更することで、デフォルトのパスからドキュメントの場所を変更したり、あるいは None を指定してドキュメント機能を完全に無効化したりすることも可能です。これは、本番環境で内部APIのドキュメントを公開したくない場合などに役立ちます。
5. セキュリティスキーム(認証・認可)のドキュメント化
API開発において認証と認可は不可欠な要素です。FastAPIはOAuth2、HTTP Basic、API Keyなどの一般的なセキュリティスキームをサポートしており、これらの設定はOpenAPIスキーマ(そしてSwagger UI)にも反映されます。
セキュリティスキームを定義し、それをエンドポイントに適用することで、Swagger UIの画面右上に「Authorize」ボタンが表示されるようになります。このボタンをクリックすると、定義したセキュリティスキームに応じた入力フィールド(例: トークン入力欄、ユーザー名/パスワード入力欄)が表示され、APIテスト時に認証情報を付加できるようになります。
FastAPIでセキュリティスキームを定義するには、fastapi.security モジュールにあるクラス(例: OAuth2PasswordBearer, HTTPBasic, APIKeyHeader など)を使用します。これらのクラスは、FastAPIの依存性注入システムと組み合わせて認証・認可ロジックを実装する際に利用されるだけでなく、その定義自体がOpenAPIスキーマに反映されるようになっています。
例:OAuth2 (JWT) を想定したBearerトークン認証
“`python
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from pydantic import BaseModel
app = FastAPI()
OAuth2PasswordBearerを定義
tokenUrl=”/token” は、トークンを取得するためのエンドポイントURLをOpenAPIスキーマに示す
oauth2_scheme = OAuth2PasswordBearer(tokenUrl=”token”)
ダミーのユーザーデータベース
fake_users_db = {
“johndoe”: {
“username”: “johndoe”,
“full_name”: “John Doe”,
“email”: “[email protected]”,
“hashed_password”: “fakehashedpassword”, # 実際にはハッシュ化されたパスワード
“disabled”: False,
}
}
ダミーのトークン検証関数
def verify_token(token: str):
# 実際にはJWTの検証、ユーザー検索、権限チェックなどを行う
# ここではシンプルに、特定のトークン以外は無効とする
if token != “fake-super-secret-token”:
return None # 検証失敗
# 検証成功したとして、ダミーユーザーを返す
return fake_users_db[“johndoe”]
認証されたユーザーを取得するための依存性
def get_current_user(token: str = Depends(oauth2_scheme)):
user = verify_token(token)
if user is None:
# HTTPExceptionを発生させると、FastAPIが自動的にOpenAPIドキュメントに401 Unauthorizedレスポンスを追加
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=”Invalid authentication credentials”,
headers={“WWW-Authenticate”: “Bearer”},
)
return user
class UserInDB(BaseModel):
username: str
full_name: str | None = None
email: str | None = None
disabled: bool | None = None
ユーザー情報を取得するAPIエンドポイント (認証が必要)
@app.get(“/users/me/”, response_model=UserInDB)
async def read_users_me(current_user: UserInDB = Depends(get_current_user)):
“””
認証ユーザーの情報を取得します。
このエンドポイントにアクセスするには認証トークンが必要です。
"""
return current_user
トークン取得エンドポイント (この例ではダミー)
@app.post(“/token”)
async def login(token: str = “fake-super-secret-token”): # ダミーのトークンを返すだけ
return {“access_token”: token, “token_type”: “bearer”}
“`
この例では、OAuth2PasswordBearer を定義し、それを依存性注入 (Depends) と組み合わせて get_current_user 関数を作成しています。get_current_user 関数は、認証トークン(Bearerトークン)を期待し、検証に失敗した場合は HTTPException(status.HTTP_401_UNAUTHORIZED) を発生させます。
@app.get("/users/me/") エンドポイントでは、get_current_user を依存性として要求しています。これにより、このエンドポイントにアクセスする際には認証が必要であることがFastAPIに伝わります。
この設定をSwagger UIで開くと、以下のようになります。
- 画面右上に「Authorize」ボタンが表示される。
- 「Authorize」ボタンをクリックすると、”oauth2PasswordBearer” というセキュリティスキームが表示され、トークン入力欄 (
Value: Bearer <token>) が表示される。 read_users_meエンドポイントの詳細を見ると、「Security」セクションに定義したセキュリティスキーム(OAuth2PasswordBearer)が表示される。- 「Try it out」機能で
read_users_meをテストする前に、まず「Authorize」ボタンでトークンを入力し、「Authorize」ボタンの下の「Logout」ボタンが表示されたら認証が完了していることを確認します。その状態で「Try it out」を実行すると、リクエストヘッダーにAuthorization: Bearer <入力したトークン>が自動的に付加されて送信されます。
HTTPExceptionを発生させた場合、FastAPIはそれが適切なHTTPステータスコード(例: 401)とそれに伴うレスポンスモデル(通常は{"detail": "..."}形式)を持つことをOpenAPIスキーマに自動的に追加してくれます。これにより、ドキュメント上でエラーレスポンスも確認できるようになります。
他のセキュリティスキーム(HTTPBasicなど)も同様に、fastapi.security の対応するクラスを使用して定義することで、Swagger UIに反映させることができます。
6. 高度なカスタマイズ
ほとんどの場合、FastAPIがデフォルトで提供するSwagger UIと、パス操作関数やPydanticモデルへのメタ情報追加で十分なドキュメントを作成できます。しかし、さらに高度なカスタマイズが必要な場合もあります。
6.1. OpenAPIスキーマへの直接アクセス
FastAPIインスタンスは、OpenAPIスキーマの生成関数 app.openapi() を持っています。この関数を呼び出すと、現在定義されているAPIに基づいたOpenAPI仕様の辞書が返されます。この辞書を直接操作することで、FastAPIの提供する引数やクラスだけでは表現できない詳細な情報を追加したり、既存の情報を変更したりすることが可能です。
“`python
from fastapi import FastAPI
import json
app = FastAPI(title=”My Custom OpenAPI”)
@app.get(“/items/”)
async def read_items():
return [{“name”: “Item 1”}]
カスタム情報をOpenAPIスキーマに追加する関数
def custom_openapi():
if app.openapi_schema:
return app.openapi_schema
# デフォルトのスキーマを生成
openapi_schema = app.openapi()
# カスタム情報を追加/変更
openapi_schema["info"]["x-custom-info"] = "このAPIはカスタム情報を含みます"
openapi_schema["paths"]["/items/"]["get"]["x-another-custom-field"] = {"note": "これはアイテムリスト取得のカスタムフィールドです"}
# 全体のServers情報を追加/変更
openapi_schema["servers"] = [
{"url": "https://api.example.com/v1", "description": "本番環境"},
{"url": "http://localhost:8000", "description": "開発環境"}
]
# Schemasにカスタム定義を追加する例(Pydanticモデルとして定義するのが一般的だが)
openapi_schema["components"]["schemas"]["CustomSchema"] = {
"type": "object",
"properties": {
"field1": {"type": "string"},
"field2": {"type": "integer"}
}
}
# 必要であれば、どこかのレスポンスなどでこのCustomSchemaを参照する
app.openapi_schema = openapi_schema
return app.openapi_schema
カスタムスキーマを公開するエンドポイント (オプション)
@app.get(“/custom-openapi.json”, include_in_schema=False) # このエンドポイント自体はドキュメントに含めない
async def get_custom_openapi():
return custom_openapi()
OpenAPIスキーマがカスタムされるように、FastAPIインスタンスのopenapi_schema属性を設定
アプリケーション起動時に一度だけカスタム処理が実行されるように工夫するのが望ましい
ここではシンプルに、毎回関数を呼び出す例を示していますが、パフォーマンス的にはキャッシュ推奨
app.openapi_schema = custom_openapi()
“`
app.openapi() を呼び出した後に返される辞書は、OpenAPI Specificationに準拠した構造になっています。この構造に従って辞書を操作することで、OpenAPI仕様が提供するあらゆる機能を活用できます。ただし、この方法はOpenAPI仕様に関する知識が必要です。
このカスタムスキーマを使用するようにFastAPIインスタンスを設定(例: app.openapi_schema = custom_openapi())することで、Swagger UIは変更後のスキーマを読み込んで表示するようになります。
6.2. カスタムSwagger UI
FastAPIは、uvicorn などASGIサーバーによって静的ファイルとしてSwagger UIを提供しています。デフォルトでは、FastAPIに組み込まれているSwagger UI(Swagger UIプロジェクトの配布ファイル)が利用されます。
もし、Swagger UIの表示設定を変更したい、特定のプラグインを組み込みたい、あるいは完全に独自のUIを用意したい場合は、以下の方法が考えられます。
- FastAPIによるカスタムホスティング: Swagger UIの静的ファイルを自分でダウンロードし、FastAPIの
StaticFilesを使ってホストします。そして、docs_url引数をNoneに設定してFastAPIのデフォルトSwagger UIを無効化し、代わりに自前でホストしたSwagger UIのエンドポイントを用意します。このカスタムHTMLファイルの中で、FastAPIが公開する/openapi.json(またはカスタムしたパス) を読み込むように設定します。 - 外部Webサーバーによるホスティング: FastAPIアプリケーションとは別に、NginxやApacheなどのWebサーバーを使ってSwagger UIの静的ファイルをホストします。この場合も、Swagger UIの設定ファイル(
swagger-ui-init.jsなど)で、FastAPIアプリケーションが提供する/openapi.json(またはカスタムパス) のURLを指定します。
例:FastAPIでカスタムSwagger UIをホストする(簡易版)
まず、Swagger UIのリリースページ から最新版のzipファイルをダウンロードし、dist ディレクトリの内容をプロジェクトの static/swagger-ui ディレクトリなどに配置します。
“`bash
例:ダウンロードして配置
mkdir static
cd static
mkdir swagger-ui
ダウンロードしたswagger-ui-dist-x.x.x.zipを解凍し、dist/ の中身を static/swagger-ui/ にコピー
“`
次にFastAPIコードを修正します。
“`python
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from starlette.responses import HTMLResponse
from starlette.routing import Mount
FastAPIインスタンス。デフォルトのSwagger UIを無効化
app = FastAPI(docs_url=None, redoc_url=None)
Swagger UIの静的ファイルをホスト
app.mount(“/swagger-ui”, StaticFiles(directory=”static/swagger-ui”), name=”swagger-ui”)
カスタムSwagger UIのエンドポイント
@app.get(“/docs”, include_in_schema=False) # このエンドポイント自体はドキュメントに含めない
async def custom_swagger_ui():
# Swagger UIのindex.htmlを読み込み、openapi.jsonのURLをFastAPIのURLに変更する
# この例では簡易的にハードコードしています。実際はファイルを読み込み、置換などが必要。
html_content = “””
<!DOCTYPE html>
“””
return HTMLResponse(content=html_content)
APIエンドポイントの定義 (省略)
@app.get(“/items/”)
async def read_items():
return [{“name”: “Item 1”}]
… 他のエンドポイント
“`
この方法では、Swagger UIの静的ファイルを自分で管理する必要がありますが、swagger-ui-init.js や index.html を修正することで、Swagger UIの様々な設定オプション(例: デフォルトで開くタグ、表示テーマ、プラグインなど)を自由にカスタマイズすることが可能になります。
6.3. ユニークなOperation IDの生成
OpenAPI仕様では、各パス操作に対してオプションでユニークな operationId を持つことができます。これはコード生成ツールなどで利用されます。FastAPIはデフォルトでは operationId を生成しませんが、FastAPI インスタンスに generate_unique_id_function 引数を渡すことで、独自の operationId 生成ロジックを指定できます。
“`python
from fastapi import FastAPI
from fastapi.routing import APIRoute
from typing import Callable
def generate_unique_id(route: APIRoute) -> str:
# 例: タグ + 関数名 をoperationIdとする
if route.tags:
# 最初に見つかったタグを使用
tag = route.tags[0]
else:
tag = “default”
# 関数名を取得
operation_id = route.name
# タグと関数名を組み合わせる
return f”{tag}-{operation_id}”
app = FastAPI(generate_unique_id_function=generate_unique_id)
@app.get(“/users/”, tags=[“Users”])
async def list_users():
return [] # operationId: Users-list_users
@app.post(“/items/”, tags=[“Items”])
async def create_item():
return {} # operationId: Items-create_item
“`
この generate_unique_id_function に渡す関数は、APIRoute オブジェクトを受け取り、文字列を返す必要があります。生成した operationId はOpenAPIスキーマに含まれ、Swagger UIの詳細画面などでも確認できるようになります(ただし、Swagger UIのデフォルト表示では目立たないかもしれません)。
7. ベストプラクティスとヒント
質の高いAPIドキュメントを自動生成するために、FastAPIの機能を最大限に活用するためのベストプラクティスをいくつか紹介します。
- 型ヒントを徹底する: FastAPIは型ヒントから多くの情報を読み取ります。関数の引数、戻り値、Pydanticモデルのフィールドなどに正確な型ヒントを付けることで、ドキュメントの精度が格段に向上します。
- Pydanticモデルを適切に利用する: リクエストボディやレスポンスボディにはPydanticモデルを使用しましょう。これにより、データ構造のスキーマが明確になり、バリデーションも容易になります。
Fieldによるメタ情報の追加: Pydanticモデルのフィールドやパラメータ (Query,Pathなど) には、Fieldを使ってdescription,example,examplesなどのメタ情報を積極的に追加しましょう。これがSwagger UIでの情報表示の質を決定づけます。- タグによるエンドポイントの整理:
tags引数を使って関連するエンドポイントをグルーピングすることで、Swagger UIのナビゲーションが非常に分かりやすくなります。API全体のopenapi_tagsでタグの説明を追加するのも効果的です。 summaryとdescriptionの使い分け:summaryはエンドポイントリストでの短い説明に、descriptionは詳細画面での詳しい説明に使います。docstringを適切に書くか、これらの引数を明示的に指定しましょう。Markdown記法も活用できます。- レスポンスモデル (
response_model) を定義する: 特に成功時のレスポンスボディの構造はresponse_modelまたは戻り値の型ヒントで明示的に指定しましょう。 - エラーレスポンス (
responses) を定義する: APIが返しうるエラー(バリデーションエラー、認証失敗、リソースNotFoundなど)についても、responses引数を使ってドキュメント化しましょう。これにより、API利用者はエラー発生時の挙動を事前に把握できます。エラーレスポンスのスキーマや例を示すと、より親切です。 - 例示 (
example,examples) を活用する: パラメータやリクエスト/レスポンスボディの例を示すことは、APIの使い方を直感的に理解してもらう上で非常に重要です。「Try it out」機能でのテストも容易になります。 - バリデーションを適切に設定する:
gt,min_lengthなどのバリデーション規則はドキュメントに反映されるだけでなく、APIの堅牢性を高めます。 include_in_schema=Falseを活用する: 内部的なエンドポイントやパラメータなど、ドキュメントに含めたくないものはinclude_in_schema=Falseを設定して非表示にしましょう。
8. トラブルシューティング
FastAPIのSwagger UIで問題が発生した場合の一般的なトラブルシューティングです。
- Swagger UI (
/docs) が表示されない:- Uvicornサーバーが正しく起動しているか確認してください。
- FastAPIインスタンス作成時に
docs_url=Noneを指定していませんか?デフォルトに戻すか、指定したカスタムパスを確認してください。 - 別のパスでSwagger UIをホストしている場合、そのパスが正しいか確認してください。
- セキュリティグループやファイアウォールなどでポートがブロックされていないか確認してください。
- エンドポイントがドキュメントに表示されない:
- そのエンドポイントのパス操作関数に
@app.get,@app.postなどのデコレーターが正しく付いていますか? - パス操作関数の引数に型ヒントが付いていますか? (必須ではありませんが、ドキュメント生成の精度に影響します)
- パス操作関数の定義で
include_in_schema=Falseを指定していませんか?
- そのエンドポイントのパス操作関数に
- パラメータやレスポンスの詳細が期待通りに表示されない:
- 型ヒントが正しいか確認してください。
- Pydanticモデルの定義が正しいか、特にフィールドの型や
Fieldの使い方が正しいか確認してください。 Query,Path,Bodyなどのクラスの引数 (description,exampleなど) が正しく指定されているか確認してください。response_modelやresponses引数が正しく設定されているか確認してください。特にresponsesのcontentやschemaの構造はOpenAPI仕様に沿っている必要があります。
- 「Try it out」機能でリクエストが失敗する:
- 入力したパラメータやリクエストボディのデータ形式が正しいか確認してください。スキーマ定義や例を参考にしてください。
- 認証が必要なエンドポイントの場合、「Authorize」ボタンで認証情報を正しく設定していますか?
- サーバー側で例外が発生していないか、サーバーのログを確認してください。
- 認証(Authorizeボタン)が表示されない、または機能しない:
fastapi.securityのセキュリティスキーム (OAuth2PasswordBearerなど) が正しく定義され、FastAPIの依存性としてパス操作関数に適用されていますか?- セキュリティスキームの定義(例:
OAuth2PasswordBearer(tokenUrl="/token")のtokenUrlなど)が正しいか確認してください。 - カスタムSwagger UIを使用している場合、セキュリティスキームの設定が正しくJavaScriptで組み込まれていますか?
9. まとめ
FastAPIの自動ドキュメント生成機能、特にSwagger UIは、API開発プロセスにおいて非常に強力なツールです。Pythonの型ヒントとPydanticモデルという、Pythonicで効率的なコーディングスタイルを推進する仕組みそのものが、高品質なAPIドキュメントを自動的に生成するための基盤となっています。
開発者は、コードに正確な型ヒントと適切なメタ情報(docstring, Field引数, パス操作関数の引数など)を記述するだけで、APIの仕様を詳細かつインタラクティブに表示するSwagger UIを手にすることができます。これにより、以下のメリットが得られます。
- 開発効率の向上: ドキュメントの手動作成・更新の手間が省け、開発者はAPIロジックの実装に集中できます。
- API仕様の明確化: コードとドキュメントが常に同期されるため、APIの実際の動作とドキュメントの間に乖離が生じにくくなります。
- テストの容易化: 「Try it out」機能を使って、ブラウザ上で手軽にAPIの動作確認やデバッグができます。
- コミュニケーションの改善: バックエンド開発者、フロントエンド開発者、API利用者など、関係者間のAPI仕様に関する共通理解を深めることができます。
本記事で解説したように、FastAPIはデフォルト機能だけでも充実したドキュメントを生成しますが、パス操作関数やパラメータ、レスポンス、さらにはAPI全体に対する詳細なカスタマイズオプションも豊富に提供されています。これらの機能を活用することで、単なる自動生成されたドキュメントではなく、真に利用者にとって分かりやすく、役立つAPIドキュメントを作成することが可能です。
FastAPIでAPIを開発する際は、ぜひこの記事を参考に、Swagger UIを最大限に活用し、質の高いAPIとドキュメント作成を目指してください。
10. 参考情報
- FastAPI 公式ドキュメント – チュートリアル: https://fastapi.tiangolo.com/tutorial/
- FastAPI 公式ドキュメント – FastAPIユーザーガイド: https://fastapi.tiangolo.com/tutorial/first-steps/ (ドキュメント生成に関する章も含まれます)
- OpenAPI Specification: https://swagger.io/specification/ (OpenAPI仕様の詳細を知りたい場合に)
- Swagger UI GitHubリポジトリ: https://github.com/swagger-api/swagger-ui
注: 本記事は約5000語を目標に記述しました。コード例や説明の詳細化に努めましたが、実際の単語数はテキスト生成ツールによって変動する可能性があります。内容としては、FastAPIのSwagger UIに関する主要な機能、カスタマイズ方法、活用方法を網羅的に解説するよう構成しています。