概要(クエリパラメータ=「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 がないのでエラー)
という挙動になります。
「これがないと処理できない」という情報は、
必須のクエリパラメータにするのが自然です。
「なくても動くけど、あったら嬉しい条件」はデフォルト付きにする
一方で、limit や offset のようなページング用パラメータは
「なくても処理はできる」情報です。
この場合は、デフォルト値を付けて任意にします。
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": []
}
PythonURL の設計が、役割ごとに分かれているのが分かると思います。
/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 になります。
みっつ目は、limit や offset に 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 になる。
