Python | Web フレームワーク:ルーティング

Python
スポンサーリンク

概要(ルーティングは「URL → 関数」の地図づくり)

ルーティングは、

「どのURLにアクセスされたら、どの関数(処理)を動かすか」

を決める仕組みです。

Webフレームワーク(FastAPI / Flask / Django など)はすべて、このルーティング機能を持っています。
URLのパス(/users/1 など)、HTTPメソッド(GET / POST など)、クエリパラメータ(?q=python など)を見て、
「このリクエストはこの関数に渡そう」と振り分けてくれます。

あなたは「ルーティングの地図」と「対応する関数」を書くだけで、「Webアプリ」「Web API」っぽい動きを作れるようになります。


ルーティングの基本イメージ(URL と HTTPメソッドで振り分け)

URL と関数を結びつける最小の例(FastAPI)

まずは、FastAPI を例に「最小ルーティング」を見てみます。

# main.py
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"message": "Hello World"}

@app.get("/health")
def health_check():
    return {"status": "ok"}
Python

これで、

  • GET / に来たら read_root
  • GET /health に来たら health_check

という対応ができます。

ここで大事なのは 2つです。

1つ目は、@app.get("/...") というデコレータ。
「この関数は、GET メソッドでこのパスに来たリクエストを処理します」という宣言です。

2つ目は、URL のパスごとに関数が分かれていること。
1ファイルにどんどんエンドポイントを増やしていくと、「URLと関数の対応表」のようになっていきます。

HTTPメソッド(GET / POST / PUT / DELETE)もルーティングの条件

同じ URL でも、HTTPメソッドが違うと別の処理にしたいことがあります。

from fastapi import FastAPI

app = FastAPI()

@app.get("/items")
def list_items():
    return ["apple", "banana"]

@app.post("/items")
def create_item():
    return {"message": "created"}
Python

GET /items は「一覧取得」
POST /items は「新規作成」

という風に分けるのが、REST風の典型的なスタイルです。

フレームワーク側は、

  • パス(/items
  • HTTPメソッド(GET or POST)

の組み合わせで、「どの関数を呼ぶか」を決めています。


パスパラメータ(URL の一部が変数になる部分)

/users/123 の「123」をどう受け取るか

ユーザーIDや商品IDのように、「URL の一部でリソースを指定したい」ケースがあります。
これが「パスパラメータ」です。

FastAPI の例で見てみます。

from fastapi import FastAPI

app = FastAPI()

@app.get("/users/{user_id}")
def get_user(user_id: int):
    return {"user_id": user_id}
Python

このルートは、

  • GET /users/1user_id=1
  • GET /users/10user_id=10

という風に、{user_id} の部分を変数として受け取れます。

ここで深掘りしたいポイントは 3つです。

1つ目は、ルート文字列に {user_id} と書いていること。
ここが「変化する部分(変数)」として扱われます。

2つ目は、関数の引数名 user_id が、ルートの {user_id} と同じ名前であること。
FastAPI は名前を見て、自動的に対応づけてくれます。

3つ目は、user_id: int と型を書いていること。
ここがものすごく大事で、FastAPI は「これは整数でなければならない」と理解します。
/users/abc のように文字列が来たら、「整数じゃない」と判断して 400 番エラーになります。

つまり、「ルーティングの定義」+「型ヒント」で、
URL から引数へのマッピングとバリデーションを同時にやってくれます。

パスパラメータをいつ使うか(設計の考え方)

一般的に、

  • リソースを一意に特定する情報(ユーザーID、商品IDなど)
  • URL の構造として「そのリソースっぽい」部分

はパスパラメータにするのがよくある設計ですg

例:

GET /users/123 → ID 123 のユーザー
GET /orders/2025-01-01 → その日の注文一覧

など。

「このURLを見ただけで、何を指しているか分かる」ようにしておくと、
自分にも他人にも優しいAPIになります。


クエリパラメータ(? 以降に付けるオプションの条件)

/search?keyword=python&limit=10 の扱い

検索条件やフィルタ、ページングなどは、クエリパラメータで渡すことが多いです。

FastAPI では、関数の引数として追加するだけでクエリパラメータを受け取れます。

from fastapi import FastAPI

app = FastAPI()

@app.get("/search")
def search_items(keyword: str, limit: int = 10, offset: int = 0):
    return {
        "keyword": keyword,
        "limit": limit,
        "offset": offset,
        "results": []
    }
Python

このエンドポイントは、

/search?keyword=apple
/search?keyword=apple&limit=5
/search?keyword=apple&limit=5&offset=10

のように呼べます。

ここでも型とデフォルト値が効いています。

  • keyword: str は必須(指定がなければエラー)
  • limit: int = 10 は省略可能(指定がなければ 10)
  • offset: int = 0 も同様

FastAPI は、URL の ? 以降を自動で解析し、
型変換(文字列 → int など)までして引数に渡してくれます。

パスパラメータとクエリパラメータの使い分け

ざっくりとした指針はこうです。

パスパラメータ
→ 「このリソースそのもの」を表す本質的な情報
→ 例:/users/123, /products/abc, /articles/2025/01/01

クエリパラメータ
→ 「どう取得/表示するか」という条件・オプション
→ 例:?page=2, ?sort=price_desc, ?keyword=python

例えば、

GET /users/123 → ユーザー 123 というリソース
GET /users?age=20&active=true → 20歳でアクティブなユーザーの検索条件

のようなイメージです。

この使い分けが自然になってくると、
ルーティング設計がかなりスッキリしてきます。


ルーティングをファイルごとに分ける(APIRouter のイメージ)

1ファイルに書き続けると、すぐに破綻する

FastAPI でルートを増やしていくと、こんな感じになりがちです。

# main.py が巨大化…
@app.get("/users")
...
@app.get("/users/{user_id}")
...
@app.post("/users")
...
@app.get("/items")
...
@app.post("/items")
...
Python

最初は問題なくても、
「ユーザー系」「商品系」「レポート系」などが混ざってくると、
どこに何があるか分かりづらくなります。

そこで使うのが APIRouter です。

APIRouter で「モジュール単位のルーティング」を作る

構成例を見てみます。

app/
  main.py
  routers/
    __init__.py
    users.py
    items.py

routers/users.py:

from fastapi import APIRouter
from pydantic import BaseModel
from typing import List

router = APIRouter(prefix="/users", tags=["users"])

class User(BaseModel):
    id: int
    name: str

fake_users = [
    User(id=1, name="Taro"),
    User(id=2, name="Hanako"),
]

@router.get("/", response_model=List[User])
def list_users():
    return fake_users

@router.get("/{user_id}", response_model=User)
def get_user(user_id: int):
    for user in fake_users:
        if user.id == user_id:
            return user
    # 本当は HTTPException を返すのが正解だが、ここでは割愛
    raise RuntimeError("not found")
Python

routers/items.py も同じように作れます。

main.py:

from fastapi import FastAPI
from routers.users import router as users_router
from routers.items import router as items_router

app = FastAPI()

app.include_router(users_router)
app.include_router(items_router)
Python

これで、

  • /users/... 系は routers/users.py
  • /items/... 系は routers/items.py

という具合に、URL 空間とファイル構造が対応します。

ここでのポイントは、

APIRouter で「このモジュールは users のルートをまとめたものです」と宣言する
main.py は、ルーターを登録するだけの「入口」にする

という構造にすることです。

ルーティングをモジュール単位で整理すると、
アプリが大きくなっても「どのファイルを見ればいいか」が一発で分かるようになります。


自動化 × ルーティングの具体イメージ(既存スクリプトをAPI化)

既存の処理を「ルートにぶら下げる」感覚

例えば、あなたがすでにこんな自動化関数を持っているとします。

# services/report.py
from datetime import date

def generate_daily_report(target_date: date) -> dict:
    # 何か重い集計
    return {
        "date": target_date.isoformat(),
        "total_sales": 12345,
        "orders": 67,
    }
Python

これを「Web API から呼べるようにする」には、
ルーティングを 1 つ用意して、その中でこの関数を呼ぶだけです。

# routers/report.py
from fastapi import APIRouter
from pydantic import BaseModel
from datetime import date
from services.report import generate_daily_report

router = APIRouter(prefix="/report", tags=["report"])

class ReportRequest(BaseModel):
    date: date

class ReportResponse(BaseModel):
    date: date
    total_sales: int
    orders: int

@router.post("/daily", response_model=ReportResponse)
def daily_report(body: ReportRequest):
    result = generate_daily_report(body.date)
    return result
Python

このルートは、

POST /report/daily に対して
{"date": "2025-01-01"} のような JSON を受け取り、
日次レポートを計算して返します。

ルーティングの役割は、

どの URL に来たら
どの関数を呼んで
どんな形の入力・出力を期待するか

を「入口として宣言する」ことです。

中身のビジネスロジック(集計処理やファイルI/Oなど)は、
従来どおり普通の Python 関数として書いておけます。


まとめ(ルーティングは「URL と関数をつなぐ宣言」)

最後に、Python Web フレームワークのルーティングを整理します。

  • ルーティングは、「URL と HTTPメソッドに応じて、どの関数を呼ぶか」を決める仕組みで、Webフレームワークの心臓部。
  • パスパラメータ(/users/{id})は「リソースを特定するための情報」を URL の一部として受け取り、型ヒントで自動バリデーションする。
  • クエリパラメータ(?q=python&limit=10)は「検索条件やオプション」を渡すのに使い、関数の引数として自然に受け取れる。
  • APIRouter(FastAPI)などで、URL 空間ごとにルートを分割すると、「ユーザー系」「商品系」などに整理されて大規模化にも耐えやすくなる。
  • 既存の自動化関数を「ルートにぶら下げる」ことで、スクリプトをそのまま Web API として公開できる。

この感覚が掴めてくると、

「この処理は /tools/xxx、これは /report/yyy かな」

と、自然に URL 設計を考えながらコードを書けるようになります。

タイトルとURLをコピーしました