Python | Web フレームワーク:クエリパラメータ

Python
スポンサーリンク

概要(クエリパラメータ=「URLの後ろにくっつく条件・オプション」)

クエリパラメータは、

/search?keyword=python&limit=10
?keyword=python&limit=10 の部分に書く「条件・オプション」のことです。

「どのデータを取るか」(ID など)はパスパラメータで指定し、
「どう取るか」「どう絞り込むか」「どう並び替えるか」を
クエリパラメータで指定する、という使い分けが基本になります。

FastAPI を例にしながら、クエリパラメータの考え方と書き方を
初心者向けに丁寧に見ていきます。


クエリパラメータの基本イメージと書式

?key=value&key2=value2 という形を押さえる

URL は大きく分けて、「パス」と「クエリ」に分かれます。

/search?keyword=python&limit=10 だったら、

パス部分:/search
クエリ部分:?keyword=python&limit=10

クエリ部分は、
先頭が ?
その後ろに key=value& でつなげて並べていきます。

この「key=value」の 1ペアが、クエリパラメータ 1 つです。

例えば、

/items?category=book&min_price=1000&in_stock=true

なら、

category = “book”
min_price = “1000”
in_stock = “true”

という 3 つのクエリパラメータがついている、ということになります。


FastAPI でのクエリパラメータの受け取り方(基本パターン)

関数の引数に書くだけで取れる

FastAPI では、クエリパラメータを特別なことをしなくても
「関数の引数」として書くだけで受け取れます。

from fastapi import FastAPI

app = FastAPI()

@app.get("/search")
def search(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

などで呼べます。

ここで押さえてほしいポイントは 3 つです。

ひとつ目は、keyword に型ヒント str を付けていることです。
FastAPI は「keyword は文字列として必須」と理解します。
keyword が指定されていないと、400 エラーになります。

ふたつ目は、limit: int = 10 のようにデフォルト値を付けていることです。
これは「省略可能なクエリパラメータ」です。
指定がなければ 10、指定があればその値(整数に変換されたもの)が入ります。

みっつ目は、型ヒントで int と書いたことで、「数値であるべき」と分かる点です。
limit=abc のようなリクエストが来たら、「整数に変換できない」と判断して 400 エラーになります。

つまり、

クエリパラメータ名=関数の引数名
型ヒント=バリデーション(型チェック)
デフォルト値=省略時の値

という対応になっています。


必須/任意をどう決めるか(設計の感覚)

「ないと意味がない条件」は必須にする

さっきの search 例でいうと、「検索キーワード」がない検索は
あまり意味がありませんよね。

なので、keyword: str とだけ書いて「必須」にします。

@app.get("/search")
def search(keyword: str):
    ...
Python

こうすると、

/search?keyword=apple → OK
/search → 400(keyword がないのでエラー)

という挙動になります。

「これがないと処理できない」という情報は、
必須のクエリパラメータにするのが自然です。

「なくても動くけど、あったら嬉しい条件」はデフォルト付きにする

一方で、limitoffset のようなページング用パラメータは
「なくても処理はできる」情報です。

この場合は、デフォルト値を付けて任意にします。

def search(keyword: str, limit: int = 10, offset: int = 0):
    ...
Python

こうすると、

/search?keyword=apple → limit=10, offset=0
/search?keyword=apple&limit=20 → limit=20, offset=0

という形になります。

設計の目安としては、

ないと実行できない → 必須(デフォルトなし)
なくても実行できる → 任意(デフォルトあり)

と考えると、クエリパラメータの必須/任意を決めやすくなります。


パスパラメータとの使い分け(ここを深く理解する)

何をパスにして、何をクエリにするか

これが Web API 設計の肝です。

例として「ユーザーの注文一覧API」を考えましょう。

パターンA:
GET /users/123/orders?limit=10&status=paid

パターンB:
GET /orders?user_id=123&limit=10&status=paid

どちらも間違いではありませんが、
意味としてはこう分解できます。

ユーザーID(123)
→ 「どのユーザーの注文か」を決める情報
→ パスパラメータ向き(対象そのもの)

limit, status
→ 「どう取得するか」の条件
→ クエリパラメータ向き(オプション・フィルタ)

FastAPI でパターンAを書いてみると、こうなります。

from fastapi import FastAPI

app = FastAPI()

@app.get("/users/{user_id}/orders")
def list_orders(
    user_id: int,
    limit: int = 10,
    status: str | None = None,
):
    return {
        "user_id": user_id,
        "limit": limit,
        "status": status,
        "orders": []
    }
Python

URL の設計が、役割ごとに分かれているのが分かると思います。

/users/{user_id}/orders → 「どこの注文か」
?limit=...&status=... → 「どう取りたいのか」

クエリパラメータは、基本的に「条件」「並び順」「ページング」などに使う、
と覚えておくと迷いにくくなります。


少し実戦寄りの例:フィルタリング・ソート・ページング

CSV や DB の「絞り込み条件」をクエリで受ける

例えば、商品一覧APIを作るとします。
条件は次のようなイメージです。

カテゴリーで絞り込みたい(category)
最低価格/最高価格で絞り込みたい(min_price / max_price)
在庫ありだけにしたい(in_stock)
ページングしたい(limit / offset)

FastAPI ではこんな感じに書けます。

from fastapi import FastAPI
from typing import Optional

app = FastAPI()

@app.get("/items")
def list_items(
    category: Optional[str] = None,
    min_price: Optional[int] = None,
    max_price: Optional[int] = None,
    in_stock: bool = False,
    limit: int = 20,
    offset: int = 0,
):
    return {
        "category": category,
        "min_price": min_price,
        "max_price": max_price,
        "in_stock": in_stock,
        "limit": limit,
        "offset": offset,
        "items": []
    }
Python

このエンドポイントは、

/items
/items?category=book&min_price=1000
/items?in_stock=true&limit=10

のように呼べます。

ここで重要な点をいくつか深掘りします。

ひとつ目は、Optional[str](または str | None)を使っていることです。
これは「指定されないこともあるし、指定されれば str が入るかもしれない」という意味です。
指定されなければ None になります。

ふたつ目は、in_stock: bool = False のような bool 型の扱いです。
?in_stock=true なら True、?in_stock=false なら False、
指定されなければデフォルトの False になります。

みっつ目は、limitoffset に int を使っていること。
文字列が来た場合は 400 でエラーになるので、「limit には数値を入れるべきだよ」という契約を自然に守らせられます。

このようにクエリパラメータを設計しておくと、
「自動化で集めた大量のデータ」をAPI越しにフィルタリングして渡すときなどに、とても扱いやすくなります。


型・デフォルト・Optional のバランス(設計の勘どころ)

何でもかんでも Optional にしない

クエリパラメータは任意で指定できるものが多いですが、
全部を Optional にしてしまうと「何も分からない」関数になってしまいます。

例えば、検索APIで keyword が Optional だとどうでしょう。

def search(keyword: Optional[str] = None):
    ...
Python

/search/search?keyword=python の両方を許してしまいます。
でも「キーワードなし」の検索ってそもそも成立するのか? という問題が出てきます。

なので、「どうしても必須な条件」は Optional にせず、
型だけ指定して必須にしてしまうほうがいいです。

def search(keyword: str, limit: int = 10):
    ...
Python

この形なら、keyword がないリクエストは弾いてくれます。

デフォルト値は「よく使う値」を埋める

デフォルト値は、
「どんなリクエストが一番よく飛んでくるか」を意識して決めると良いです。

たとえば、

ページングの limit → 20 または 50 など
in_stock → False(全件)ではなく True(在庫ありのみ)にしたいケースもある

など、「実務的に一番よく使う設定」をデフォルトにしておくと、
クライアント側の指定が楽になり、使い勝手が上がります。


まとめ(クエリパラメータは「動作を微調整するツマミ」)

クエリパラメータを、自動化+Web API の視点で整理すると、こうなります。

クエリパラメータは、?key=value&key2=value2 の形で URL にぶら下がる「条件・オプション」で、FastAPI では関数の引数として自然に受け取れる。
型ヒント(str / int / bool など)とデフォルト値を使うことで、「必須か任意か」「どんな値が許されるか」を宣言的に書ける(FastAPI が型変換とエラー判定をやってくれる)。
パスパラメータは「対象そのもの」(ユーザーIDなど)、クエリパラメータは「どう取得するかの条件」(検索キーワード、ページング、フィルタ)という役割分担を意識すると URL 設計がきれいになる。
複数のクエリパラメータ(category、min_price、max_price、limit、offset など)を組み合わせることで、自動化で扱う大量データの検索・絞り込み・ソートを柔軟に制御できる。
Optional とデフォルト値を「適当に」ではなく、「本当に必須なものは必須にし、よく使う設定はデフォルトにする」という方針で決めると、使いやすい API になる。

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