概要(パスパラメータ=「URLの中の変数」)
パスパラメータは、
/users/123 の「123」/items/abc の「abc」
のように、URL の一部を「変数」として受け取る仕組みです。
Web フレームワーク(FastAPI / Flask / Django など)では、
この「URL の一部」を関数の引数として受け取れるようにしておくことで、
「どのユーザーを表示するか」
「どの商品を取得するか」
といった「対象を指定する情報」をスマートに扱えます。
ここでは FastAPI を例にしながら、パスパラメータを初心者向けにじっくり解説していきます。
パスパラメータの一番基本形(FastAPI)
固定パスとパスパラメータの違いを知る
まず、「普通の固定パス」と「パスパラメータ」を対比してみます。
固定パスの例(いつも同じ URL):
from fastapi import FastAPI
app = FastAPI()
@app.get("/hello")
def say_hello():
return {"message": "hello"}
Pythonこれは GET /hello に対してだけ反応します。
URL の一部が変わると別ルートになります。
次に、パスパラメータの例です。
from fastapi import FastAPI
app = FastAPI()
@app.get("/users/{user_id}")
def get_user(user_id: str):
return {"user_id": user_id}
Pythonこのエンドポイントは、
/users/1/users/taro/users/xyz-123
など、{user_id} の部分が何であっても受け取ることができます。
この {user_id} が「パスパラメータ」です。
URL のテンプレート /users/{user_id} を定義しておくことで、user_id という名前の引数に、URL の一部が自動で渡されます。
名前の対応が重要({user_id} ↔ user_id 引数)
さっきの例で、ルートと関数の定義をもう一度見てください。
@app.get("/users/{user_id}")
def get_user(user_id: str):
...
Python{user_id} と user_id
名前が完全に一致しています。
FastAPI は、「パスに書かれた {user_id}」「関数の引数 user_id」を見て、そこを紐づけています。
もし名前を変えると、FastAPI は対応できません。
@app.get("/users/{user_id}")
def get_user(id: str): # NG: 名前が違う
...
Pythonこのように書くと、「user_id というパラメータを引数に渡そうとしているのに、id が定義されている」となって不整合です。
パスパラメータでは「名前の一致」が絶対ルールです。
型ヒントでパスパラメータを「強く」する(ここが FastAPI の美味しいところ)
文字列だけでなく、整数などの型も指定できる
FastAPI の強みは、「パスパラメータに型を付けられる」ことです。
@app.get("/users/{user_id}")
def get_user(user_id: int):
return {"user_id": user_id}
Pythonこの場合、FastAPI は user_id を「整数」として扱います。
URL 側は文字列ですが、フレームワークが内部で int(user_id) を試みます。
もし /users/10 のように数字が来れば、user_id は整数 10 になります。
もし /users/abc のように数字以外が来たら、「整数に変換できない」と判断して 400 エラー(Bad Request)を返してくれます。
つまり、
user_id: int と書くだけで、「整数であることのチェック」を自動でやってくれる
わけです。
これが「型ヒントがバリデーションになる」という FastAPI の気持ち良さです。
よく使う型の例
パスパラメータに使える型はいろいろありますが、初心者ならまずは次のあたりを押さえておけば十分です。
str: 文字列。何でも受け取れる。int: 整数。123 など。float: 実数。1.23 など。
これらはすべて、「型ヒントを書く → FastAPI が変換+チェックしてくれる」流れです。
例えば、商品のIDが整数なら int、コードが文字列なら str にしておくと、
「ありえない値(文字列のIDを期待しているのに数字だけ」など)を早めに弾けます。
複数のパスパラメータを使う(URL の構造をきれいに設計する)
例:年月日をパスで受け取る
日付を /reports/2025/01/01 のように分けて渡したい場合を考えます。
from fastapi import FastAPI
app = FastAPI()
@app.get("/reports/{year}/{month}/{day}")
def daily_report(year: int, month: int, day: int):
return {
"date": f"{year:04d}-{month:02d}-{day:02d}"
}
Pythonこのルーティングは、
GET /reports/2025/1/2 → year=2025, month=1, day=2GET /reports/2024/12/31 → year=2024, month=12, day=31
という風に動きます。
ここでも「名前の対応」と「型」が重要です。
パス:
/reports/{year}/{month}/{day}
関数:
def daily_report(year: int, month: int, day: int):
このように位置と名前を揃えておくことで、FastAPI が自動でマッピングしてくれます。
パス設計の考え方(見た瞬間に意味が分かる URL にする)
パスパラメータを使うときに意識してほしいのは、「URL の形だけで意味が伝わるか」です。
/reports/2025/01/01 → 2025-01-01 のレポート/users/123/orders → ユーザー123の注文一覧
このように、URL を見ただけで「ああ、このリソースだな」と分かる構造にしておくと、
自分も他人も API が理解しやすくなります。
パスパラメータとクエリパラメータの違い(ここをはっきりさせる)
パスパラメータは「対象そのもの」、クエリは「条件」
とても大事な区別なので、少し丁寧に説明します。
例えば、ユーザーの注文履歴を取る API を考えてみます。
GET /users/123/ordersGET /users/123/orders?limit=10&offset=20
この場合、
123 → ユーザーという「対象そのもの」を特定する情報(パスパラメータ)limit=10、offset=20 → 「どう取得するか」の条件(クエリパラメータ)
という分け方になります。
FastAPI で書くとこうです。
from fastapi import FastAPI
app = FastAPI()
@app.get("/users/{user_id}/orders")
def list_orders(user_id: int, limit: int = 10, offset: int = 0):
return {
"user_id": user_id,
"limit": limit,
"offset": offset,
"orders": []
}
Pythonuser_id はパスパラメータとして URL に含め、limit と offset はクエリパラメータとして ?limit=...&offset=... で渡します。
設計の目安としては、
「この情報がないと、どのリソースか分からない」
→ パスパラメータ
「この情報がなくても、とりあえずは取れる(ただし条件なし)」
→ クエリパラメータ
と考えると、だいたいしっくり来ます。
パスパラメータを使うときの注意ポイント(初心者がハマりやすいところ)
1. パスの順番と具体性(/users/me と /users/{user_id})
FastAPI では、「どのルートにマッチさせるか」がパスの定義順や具体性に影響されます。
例えば、次のようなコードを考えます。
from fastapi import FastAPI
app = FastAPI()
@app.get("/users/me")
def get_me():
return {"user": "current"}
@app.get("/users/{user_id}")
def get_user(user_id: str):
return {"user_id": user_id}
Pythonこの場合、
/users/me は「固定パス」/users/{user_id} は「何でもマッチするパス」
FastAPI は「より具体的なパスを優先」するので、/users/me にアクセスしたときは get_me が呼ばれます。
もし順番を逆にしても(FastAPI はパスの具体性で判断するので)大丈夫ですが、
Flask などフレームワークによっては「上から順にマッチ」もあるので、
「固定パス」と「なんでもパラメータ」の組み合わせには注意したほうが安全です。
FastAPI では、
/users/me/users/{user_id}
のような組み合わせはよく使われます
ログイン中ユーザー専用 → /users/me
任意のユーザー → /users/{user_id}
のような形で使い分けられます。
2. 型変換とエラー(パスに入る値は信じない)
user_id: int と書いた場合、FastAPI が型変換とチェックをしてくれますが、
「失敗することも前提」で考える必要があります。
/users/abc のようなリクエストが来るかもしれない/reports/2025/13/32 のように、存在しない日付が来るかもしれない
こういう場合は、型レベルでは OK(全部 int)でも、意味的には NG です。
year, month, day を受け取ったあとで、
Python の datetime で日付として有効か確認するなど、
「意味的なバリデーション」は自分で書く必要があります。
例えば:
from fastapi import FastAPI, HTTPException
from datetime import date
app = FastAPI()
@app.get("/reports/{year}/{month}/{day}")
def daily_report(year: int, month: int, day: int):
try:
target_date = date(year, month, day)
except ValueError:
raise HTTPException(status_code=400, detail="Invalid date")
return {"date": target_date.isoformat()}
Pythonこうしておくと、
/reports/2025/1/2 → OK/reports/2025/13/32 → 400(無効な日付)
という動きになります。
パスパラメータの「型チェック」は FastAPI がやってくれますが、
「値として妥当かどうか」のチェックは自分の仕事、という意識を持っておくと安全です。
まとめ(パスパラメータは「URLでリソースを指すための変数」)
パスパラメータを、自分の中で整理するとこうなります。
パスパラメータは、/users/{id} の {id} のように、「URLの一部」を変数として受け取る仕組みで、対象のリソース(ユーザー・商品・日付など)を指定するのに使う。
FastAPI では、ルートに /users/{user_id} と書き、関数に user_id: int などと型付き引数を定義すると、URL → 引数 のマッピング+型チェックを自動でやってくれる。
「その情報がないとどのリソースか分からない」ものはパスパラメータ、「あると便利だがなくてもとりあえず動く」条件はクエリパラメータにする、という分け方を意識すると URL 設計がきれいになる。
パスパラメータを複数組み合わせて /reports/{year}/{month}/{day} のような構造を作ると、「URLを見ただけで意味が分かる」APIになる。
型チェックはやってくれるが、「意味として妥当か」(日付・範囲・存在チェックなど)は自分でバリデーションを書く必要がある。
