コンテンツにスキップ

クエリパラメータ

パスパラメータではない関数パラメータを宣言すると、それらは自動的に "クエリ" パラメータとして解釈されます。

from fastapi import FastAPI

app = FastAPI()

fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]


@app.get("/items/")
async def read_item(skip: int = 0, limit: int = 10):
    return fake_items_db[skip : skip + limit]

クエリはURL内で ? の後に続くキーとバリューの組で、 & で区切られています。

例えば、以下の様なURL内で:

http://127.0.0.1:8000/items/?skip=0&limit=10

...クエリパラメータは:

  • skip: 値は 0
  • limit: 値は 10

これらはURLの一部なので、「自然に」文字列になります。

しかしPythonの型を宣言すると (上記の例では int として)、その型に変換されバリデーションが行われます。

パスパラメータに適用される処理と完全に同様な処理がクエリパラメータにも施されます:

  • エディターサポート (明らかに)
  • データ「解析
  • データバリデーション
  • 自動ドキュメント生成

デフォルト

クエリパラメータはパスの固定部分ではないので、オプショナルとしたり、デフォルト値をもつことができます。

上述の例では、skip=0limit=10 というデフォルト値を持っています。

したがって、以下のURLにアクセスすることは:

http://127.0.0.1:8000/items/

以下のURLにアクセスすることと同等になります:

http://127.0.0.1:8000/items/?skip=0&limit=10

しかし、例えば、以下にアクセスすると:

http://127.0.0.1:8000/items/?skip=20

関数内のパラメータの値は以下の様になります:

  • skip=20: URL内にセットしたため
  • limit=10: デフォルト値

オプショナルなパラメータ

同様に、デフォルト値を None とすることで、オプショナルなクエリパラメータを宣言できます:

from typing import Union

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_item(item_id: str, q: Union[str, None] = None):
    if q:
        return {"item_id": item_id, "q": q}
    return {"item_id": item_id}
🤓 Other versions and variants
from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_item(item_id: str, q: str | None = None):
    if q:
        return {"item_id": item_id, "q": q}
    return {"item_id": item_id}

この場合、関数パラメータ q はオプショナルとなり、デフォルトでは None になります。

確認

パスパラメータ item_id はパスパラメータであり、q はそれとは違ってクエリパラメータであると判別できるほどFastAPI が賢いということにも注意してください。

クエリパラメータの型変換

bool 型も宣言できます。これは以下の様に変換されます:

from typing import Union

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_item(item_id: str, q: Union[str, None] = None, short: bool = False):
    item = {"item_id": item_id}
    if q:
        item.update({"q": q})
    if not short:
        item.update(
            {"description": "This is an amazing item that has a long description"}
        )
    return item
🤓 Other versions and variants
from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_item(item_id: str, q: str | None = None, short: bool = False):
    item = {"item_id": item_id}
    if q:
        item.update({"q": q})
    if not short:
        item.update(
            {"description": "This is an amazing item that has a long description"}
        )
    return item

この場合、以下にアクセスすると:

http://127.0.0.1:8000/items/foo?short=1

もしくは、

http://127.0.0.1:8000/items/foo?short=True

もしくは、

http://127.0.0.1:8000/items/foo?short=true

もしくは、

http://127.0.0.1:8000/items/foo?short=on

もしくは、

http://127.0.0.1:8000/items/foo?short=yes

もしくは、他の大文字小文字のバリエーション (アッパーケース、最初の文字だけアッパーケース、など)で、関数は short パラメータを Truebool 値として扱います。それ以外は False になります。

複数のパスパラメータとクエリパラメータ

複数のパスパラメータとクエリパラメータを同時に宣言できます。FastAPIは互いを区別できます。

そして特定の順序で宣言しなくてもよいです。

名前で判別されます:

from typing import Union

from fastapi import FastAPI

app = FastAPI()


@app.get("/users/{user_id}/items/{item_id}")
async def read_user_item(
    user_id: int, item_id: str, q: Union[str, None] = None, short: bool = False
):
    item = {"item_id": item_id, "owner_id": user_id}
    if q:
        item.update({"q": q})
    if not short:
        item.update(
            {"description": "This is an amazing item that has a long description"}
        )
    return item
🤓 Other versions and variants
from fastapi import FastAPI

app = FastAPI()


@app.get("/users/{user_id}/items/{item_id}")
async def read_user_item(
    user_id: int, item_id: str, q: str | None = None, short: bool = False
):
    item = {"item_id": item_id, "owner_id": user_id}
    if q:
        item.update({"q": q})
    if not short:
        item.update(
            {"description": "This is an amazing item that has a long description"}
        )
    return item

必須のクエリパラメータ

パスパラメータ以外のパラメータ (今のところ、クエリパラメータのみ説明しました) のデフォルト値を宣言した場合、そのパラメータは必須ではなくなります。

特定の値を与えずにただオプショナルにしたい場合はデフォルト値を None にして下さい。

しかしクエリパラメータを必須にしたい場合は、ただデフォルト値を宣言しなければよいです:

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_user_item(item_id: str, needy: str):
    item = {"item_id": item_id, "needy": needy}
    return item

ここで、クエリパラメータ needystr 型の必須のクエリパラメータです

以下のURLをブラウザで開くと:

http://127.0.0.1:8000/items/foo-item

...必須のパラメータ needy を加えなかったので、以下の様なエラーが表示されます:

{
    "detail": [
        {
            "loc": [
                "query",
                "needy"
            ],
            "msg": "field required",
            "type": "value_error.missing"
        }
    ]
}

needy は必須のパラメータなので、URLにセットする必要があります:

http://127.0.0.1:8000/items/foo-item?needy=sooooneedy

...これはうまくいくでしょう:

{
    "item_id": "foo-item",
    "needy": "sooooneedy"
}

そして当然、あるパラメータを必須に、別のパラメータにデフォルト値を設定し、また別のパラメータをオプショナルにできます:

from typing import Union

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_user_item(
    item_id: str, needy: str, skip: int = 0, limit: Union[int, None] = None
):
    item = {"item_id": item_id, "needy": needy, "skip": skip, "limit": limit}
    return item
🤓 Other versions and variants
from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_user_item(
    item_id: str, needy: str, skip: int = 0, limit: int | None = None
):
    item = {"item_id": item_id, "needy": needy, "skip": skip, "limit": limit}
    return item

この場合、3つのクエリパラメータがあります。:

  • needy、必須の str
  • skip、デフォルト値を 0 とする int
  • limit、オプショナルな int

豆知識

パスパラメータと同様に Enum を使用できます。