404 Not Found

404 Not Found


nginx

Path Parameters and Query Parameters — Precision Routing Design

ルーティング設計は都市の道路計画のようなものです。Path Parameters は住所 (正確な位置), Query Parameters は絞り込み条件 (範囲の限定)であり, この2つが連携してはじめて目的地に素早くたどり着けます。

1. 学ぶ内容


2. Alice のリアルストーリー

(1) ペインポイント:商品検索 API のパラメータが混乱

Alice の PriceTracker は複数の検索方法に対応する必要があります:商品 ID による正確な検索, カテゴリと価格範囲によるフィルタリング, ソート順によるページネーション閲覧です。Bob はフロントエンドから category=electronics&min_price=10&max_price=999 を送信しましたが, Alice の Flask コードは各パラメータを手動でパースしています。型変換でエラーが起きやすく, 負の価格や無効なソートフィールドに対するバリデーションもないため, 本番環境でのインシデントが頻発しています。

(2) FastAPI におけるパラメータバリデーションの解決策

FastAPI は型ヒントを使用してパラメータを自動的にパース・バリデーションします。Path()Query() は宣言的な制約を提供し, 無効なパラメータは自動的に 422 エラーをトリガーします。

PYTHON
from fastapi import FastAPI, Path, Query

app = FastAPI()

@app.get("/products/{product_id}")
async def get_product(
    product_id: int = Path(gt=0, description="Product ID must be positive"),
    category: str | None = Query(None, max_length=50),
):
    return {"product_id": product_id, "category": category}

(3) 成果

パラメータバリデーションコードは 30 行から 3 行に削減され, 422 エラーレスポンスにはバリデーション失敗の具体的な詳細が自動的に含まれるようになり, Bob はどのパラメータが間違っているかをすぐに特定できます。API ドキュメントにもすべての制約が自動的に表示されます。


3. Path Parameters の詳細解説

(1) 基本的な Path Parameters

Path Parameters は URL パスの一部であり, {param} 構文で定義します。FastAPI は型ヒントに基づいて自動的に変換します。

100%
sequenceDiagram
    participant Client
    participant Router as FastAPI Router
    participant Converter as Type Converter
    participant Validator as Path Validator
    participant Handler as View Function

    Client->>Router: GET /products/42
    Router->>Converter: Extract "42" from path
    Converter->>Converter: int("42") → 42
    Converter->>Validator: product_id=42 (int)
    Validator->>Validator: Check gt=0 → 42 > 0 ✓
    Validator->>Handler: get_product(product_id=42)
    Handler-->>Client: {"product_id": 42}
Path Parameter 型 URL 例 Python 型 自動変換
整数 /products/42 int "42"42
浮動小数点数 /prices/9.99 float "9.99"9.99
文字列 /categories/electronics str そのまま
Path /files/src/main.py Path / を含む文字列

(1) ▶ サンプル:基本的な Path Parameters と型変換

PYTHON
from fastapi import FastAPI

app = FastAPI()

@app.get("/products/{product_id}")
async def get_product(product_id: int):
    # FastAPI は自動的に "42" を int(42) に変換
    # ユーザーが /products/abc を送信 → 422 エラー
    return {"product_id": product_id, "type": str(type(product_id))}

出力:

TEXT
INFO:     127.0.0.1:50123 - "GET /api/items HTTP/1.1" 200 OK

出力 (/products/42):

TEXT
{"product_id": 42, "type": "<class 'int'>"}

(2) Path() 制約バリデーション

Path() は Path Parameters に数値範囲や文字列長などの制約を追加します。これらは OpenAPI ドキュメントに自動的に反映されます。

制約パラメータ 対象型 意味
gt int/float より大きい (>)
ge int/float 以上 (>=)
lt int/float より小さい (<)
le int/float 以下 (<=)
min_length str 最小長
max_length str 最大長
pattern str 正規表現マッチ
description 全型 OpenAPI 説明

(2) ▶ サンプル:Path() 数値制約

PYTHON
from fastapi import FastAPI, Path

app = FastAPI()

@app.get("/products/{product_id}")
async def get_product(
    product_id: int = Path(
        gt=0,
        le=1000000,
        description="Product ID: 正の整数, 最大100万",
    ),
):
    return {"product_id": product_id}

出力:

TEXT
INFO:     127.0.0.1:50123 - "GET /api/items HTTP/1.1" 200 OK

出力 (/products/-1 は 422 を返す):

TEXT
{
  "detail": [
    {
      "loc": ["path", "product_id"],
      "msg": "Input should be greater than 0",
      "type": "greater_than"
    }
  ]
}

4. Query Parameters の詳細解説

(1) 基本的な Query Parameters

Query Parameters は URL の ? に続くキーと値のペアです。関数パラメータとして宣言され, デフォルト値を持つパラメータは任意です。

Query Parameter 型 宣言方法 必須
必須 category: str はい
任意 (デフォルト) category: str = "all" いいえ
任意 (None) `category: str None = None`

(1) ▶ サンプル:Query Parameter の基本

PYTHON
from fastapi import FastAPI, Query

app = FastAPI()

@app.get("/prices")
async def search_prices(
    category: str | None = Query(None, max_length=50, description="商品カテゴリ"),
    min_price: float = Query(0.0, ge=0, description="最低価格 (USD)"),
    max_price: float = Query(999999.0, le=999999, description="最高価格 (USD)"),
):
    return {
        "category": category,
        "price_range": f"${min_price} - ${max_price}",
    }

出力:

TEXT
INFO:     127.0.0.1:50123 - "GET /api/items HTTP/1.1" 200 OK

出力 (/prices?category=electronics&min_price=10&max_price=500):

TEXT
{"category": "electronics", "price_range": "$10.0 - $500.0"}

(2) Query() 高度なオプション

オプション 機能
alias パラメータのエイリアス (例:キャメルケース→スネークケース) Query(alias="minPrice")
deprecated 廃止予定としてマーク Query(deprecated=True)
title OpenAPI タイトル Query(title="Category Filter")
description OpenAPI 説明 Query(description="...")
examples サンプル値 Query(examples=["electronics"])

(2) ▶ サンプル:alias と deprecated

PYTHON
from fastapi import FastAPI, Query

app = FastAPI()

@app.get("/products")
async def list_products(
    sort_by: str = Query(
        "name",
        alias="sortBy",
        description="Sort field: name, price, created_at",
    ),
    old_filter: str | None = Query(
        None,
        deprecated=True,
        description="sort_by を代わりに使用",
    ),
):
    return {"sort_by": sort_by}

出力:

TEXT
# 関数定義成功

5. 列挙パラメータ

(1) 文字列列挙で可能な値を制限

パラメータが固定の値しか取れない場合, Enum 制約を使用すると, FastAPI はドキュメントにドロップダウンメニューを自動表示します。

(1) ▶ サンプル:列挙 Path Parameters

PYTHON
from enum import Enum
from fastapi import FastAPI

class Category(str, Enum):
    electronics = "electronics"
    clothing = "clothing"
    food = "food"
    books = "books"

app = FastAPI()

@app.get("/categories/{category}")
async def get_category(category: Category):
    return {
        "category": category,
        "value": category.value,
        "label": category.name,
    }

出力:

TEXT
INFO:     127.0.0.1:50123 - "GET /api/items HTTP/1.1" 200 OK

出力 (/categories/electronics):

TEXT
{"category": "electronics", "value": "electronics", "label": "electronics"}

(2) ▶ サンプル:列挙 Query Parameters とソート

PYTHON
from enum import Enum
from fastapi import FastAPI, Query

class SortOrder(str, Enum):
    asc = "asc"
    desc = "desc"

app = FastAPI()

@app.get("/products")
async def list_products(
    sort_order: SortOrder = Query(SortOrder.asc),
    limit: int = Query(20, ge=1, le=100),
    offset: int = Query(0, ge=0),
):
    return {
        "sort": sort_order.value,
        "limit": limit,
        "offset": offset,
    }

出力:

TEXT
# 関数定義成功

6. 複数パラメータの組み合わせと落とし穴

(1) パラメータ宣言の順序ルール

FastAPI のパラメータ型判定ルール:パスに {param} が含まれていれば Path Parameter, そうでなければ Query Parameter です (型アノテーションのあるパラメータは必須, デフォルト値のあるものは任意)。

順序 パラメータ型 判定基準
1 Path Parameter URL に {param} が含まれる
2 Query Parameter (必須) デフォルト値なし, パスに含まれない
3 Query Parameter (任意) デフォルト値または None を持つ

(1) ▶ サンプル:複数パラメータの組み合わせ — PriceTracker 商品検索

PYTHON
from fastapi import FastAPI, Path, Query
from enum import Enum

class Category(str, Enum):
    electronics = "electronics"
    clothing = "clothing"
    food = "food"

app = FastAPI()

@app.get("/products/{product_id}/prices")
async def get_product_prices(
    product_id: int = Path(gt=0, description="商品 ID"),
    category: Category | None = Query(None, description="カテゴリでフィルタ"),
    min_price: float = Query(0.0, ge=0, description="最低価格 (USD)"),
    max_price: float = Query(99999.0, ge=0, description="最高価格 (USD)"),
    sort: str = Query("date", pattern="^(date|price)$"),
    limit: int = Query(20, ge=1, le=100),
    offset: int = Query(0, ge=0),
):
    return {
        "product_id": product_id,
        "category": category,
        "price_range": [min_price, max_price],
        "sort": sort,
        "pagination": {"limit": limit, "offset": offset},
    }

出力:

TEXT
# 関数定義成功

(2) よくある落とし穴

落とし穴 誤った構文 正しい構文
Path Parameter を任意にする product_id: int = None Path Parameter は必須
デフォルト値と Query の競合 limit: int = 20, Query(ge=1) limit: int = Query(20, ge=1)
任意パラメータの None category: str = None `category: str
Enum で str 基底クラスを使わない class Cat(Enum): class Cat(str, Enum):

7. 総合サンプル

Path Parameters, Query Parameters, Enum 制約は柔軟な API 構築の基盤です。以下では, Path 制約, Query ページネーション, Enum フィルタリングを組み合わせます。

PYTHON
from fastapi import FastAPI, Path, Query
from enum import Enum

app = FastAPI()

class SortOrder(str, Enum):
    asc = "asc"
    desc = "desc"

PRODUCTS = [{"id": i, "name": f"Product-{i}", "price": i * 10.0} for i in range(1, 101)]

@app.get("/products/{product_id}")
async def get_product(
    product_id: int = Path(gt=0, description="商品 ID"),
    sort: SortOrder = Query(SortOrder.asc),
    limit: int = Query(10, ge=1, le=100),
    offset: int = Query(0, ge=0),
):
    return {
        "product_id": product_id,
        "sort": sort.value,
        "limit": limit,
        "offset": offset,
    }

出力:

TEXT
GET /products/5?sort=desc&limit=20&offset=10 → {"product_id":5,"sort":"desc","limit":20,"offset":10}
GET /products/0 → 422 Validation Error (product_id must be > 0)

❓ よくある質問

Q Path Parameters と Query Parameters は同じ名前にできますか?
A いいえ。FastAPI は同じ名前のパラメータを区別できないため, エラーが発生します。
Q Query Parameter を必須にするにはどうすればよいですか?
A デフォルト値を指定しないだけです。例えば, category: str は必須, category: str = "all" は任意です。Query(...) を使って明示的に必須とマークすることもできます。
Q 詳細すぎるエラーメッセージ (422 エラーなど)は機密情報を漏洩しませんか?
A 開発中は詳細なエラーメッセージが役立ちます。本番環境では, カスタム例外ハンドラを使用してレスポンスを簡略化し, 「パラメータバリデーションに失敗しました」とだけ返すことができます。
Q Enum パラメータは小文字を受け付けますか?
A デフォルトでは大文字小文字を区別します。大文字小文字を区別しないようにするには, カスタムバリデータを定義するか, Enum 値で小文字を使用する必要があります。
Q Path() の "gt" と "ge" の違いは何ですか?
A gt=0 は値が > 0 (0 を含まない), ge=0 は >= 0 (0 を含む)を意味します。ID 型のパラメータには通常 gt=0, 価格型のパラメータには ge=0 を使用します。
Q Query Parameters の長さを制限するにはどうすればよいですか?
A Query(max_length=N) で文字列の長さを制限し, Query(ge=N, le=M) で数値範囲を制限します。

📖 まとめ


📝 練習問題

  1. 基本問題 (難易度 ⭐):GET エンドポイント /items/{item_id} を作成し, item_id (正の整数)を入力として受け取り, {"item_id": item_id} を返すようにしてください。ヒント:item_id: int = Path(gt=0)
  2. 応用問題 (難易度 ⭐⭐):PriceTracker の /products クエリエンドポイントを作成し, 3 つの Query Parameters をサポートしてください:category (任意の文字列, 最大50文字), min_price (≥0), max_price (≤999999)。ヒント:Query(None, max_length=50)
  3. チャレンジ問題 (難易度 ⭐⭐⭐):/products/{product_id}/prices エンドポイントを作成し, Path Parameters (product_id > 0), 列挙 Query Parameters (SortOrder: asc/desc), ページネーションパラメータ (limit 1-100, offset ≥ 0)を使用して, 無効な入力が 422 エラーを返すことを確認してください。ヒント:SortOrder(str, Enum) と複数の Query() を定義

---|

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%