コンテンツにスキップ

パス パラメータと数値検証

Queryを使用してクエリ パラメータの検証とメタデータを宣言できるのと同様に、Pathを使用してパス パラメータの同じタイプの検証とメタデータを宣言できます。

パスのインポート

まず、fastapiからPathをインポートし、Annotatedをインポートします。

from typing import Annotated

from fastapi import FastAPI, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get")],
    q: Annotated[str | None, Query(alias="item-query")] = None,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
from typing import Annotated, Union

from fastapi import FastAPI, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get")],
    q: Annotated[Union[str, None], Query(alias="item-query")] = None,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
from typing import Union

from fastapi import FastAPI, Path, Query
from typing_extensions import Annotated

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get")],
    q: Annotated[Union[str, None], Query(alias="item-query")] = None,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

ヒント

可能であれば、Annotatedバージョンを使用することをお勧めします。

from fastapi import FastAPI, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: int = Path(title="The ID of the item to get"),
    q: str | None = Query(default=None, alias="item-query"),
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

ヒント

可能であれば、Annotatedバージョンを使用することをお勧めします。

from typing import Union

from fastapi import FastAPI, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: int = Path(title="The ID of the item to get"),
    q: Union[str, None] = Query(default=None, alias="item-query"),
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

情報

FastAPIはバージョン0.95.0でAnnotatedのサポートを追加し(推奨を開始しました)。

古いバージョンを使用している場合、Annotatedを使用しようとするとエラーが発生します。

Annotatedを使用する前に、FastAPIのバージョンを少なくとも0.95.1にアップグレードしてください。

メタデータの宣言

Queryと同じパラメータをすべて宣言できます。

たとえば、パス パラメータitem_idtitleメタデータ値を宣言するには、次のように入力します。

from typing import Annotated

from fastapi import FastAPI, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get")],
    q: Annotated[str | None, Query(alias="item-query")] = None,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
from typing import Annotated, Union

from fastapi import FastAPI, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get")],
    q: Annotated[Union[str, None], Query(alias="item-query")] = None,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
from typing import Union

from fastapi import FastAPI, Path, Query
from typing_extensions import Annotated

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get")],
    q: Annotated[Union[str, None], Query(alias="item-query")] = None,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

ヒント

可能であれば、Annotatedバージョンを使用することをお勧めします。

from fastapi import FastAPI, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: int = Path(title="The ID of the item to get"),
    q: str | None = Query(default=None, alias="item-query"),
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

ヒント

可能であれば、Annotatedバージョンを使用することをお勧めします。

from typing import Union

from fastapi import FastAPI, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: int = Path(title="The ID of the item to get"),
    q: Union[str, None] = Query(default=None, alias="item-query"),
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

注記

パス パラメータは、パスの

必要に応じてパラメータを並べ替える

ヒント

Annotatedを使用する場合、これはそれほど重要ではないか、必要ない可能性があります。

クエリ パラメータqを必須のstrとして宣言したいとします。

また、そのパラメータには他に何も宣言する必要がないため、実際にはQueryを使用する必要はありません。

しかし、それでもitem_idパス パラメータにはPathを使用する必要があります。そして、何らかの理由でAnnotatedを使用したくないとします。

「デフォルト」値を持つ値を、「デフォルト」値を持たない値の前に配置すると、Pythonはエラーを発生させます。

しかし、それらを並べ替えて、デフォルトのない値(クエリ パラメータq)を最初に配置することができます。

FastAPIには関係ありません。名前、型、およびデフォルト宣言(QueryPathなど)によってパラメータを検出します。順序は関係ありません。

そのため、関数を次のように宣言できます。

ヒント

可能であれば、Annotatedバージョンを使用することをお勧めします。

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(q: str, item_id: int = Path(title="The ID of the item to get")):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

ただし、Annotatedを使用する場合、この問題は発生せず、Query()またはPath()に関数パラメータのデフォルト値を使用していないため、問題になりません。

from typing import Annotated

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    q: str, item_id: Annotated[int, Path(title="The ID of the item to get")]
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
from fastapi import FastAPI, Path
from typing_extensions import Annotated

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    q: str, item_id: Annotated[int, Path(title="The ID of the item to get")]
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

必要に応じてパラメータを並べ替える、コツ

ヒント

Annotatedを使用する場合、これはそれほど重要ではないか、必要ない可能性があります。

これは便利な**ちょっとしたコツ**ですが、頻繁に必要になることはありません。

したい場合

  • Queryもデフォルト値も使用せずに、クエリパラメータqを宣言します。
  • Pathを使用して、パス パラメータitem_idを宣言します。
  • それらを異なる順序で配置します。
  • Annotatedを使用しません。

...Pythonには、それのための特別な構文があります。

関数の最初のパラメータとして*を渡します。

Pythonは、その*では何も行いませんが、後続のすべてのパラメータは、キーワード引数(キーと値のペア)、別名kwargsとして呼び出す必要があることを認識します。 デフォルト値がない場合でも同様です。

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(*, item_id: int = Path(title="The ID of the item to get"), q: str):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

Annotatedを使用する方が良い

Annotatedを使用する場合、関数パラメータのデフォルト値を使用していないため、この問題は発生せず、*を使用する必要はないでしょう。

from typing import Annotated

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get")], q: str
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
from fastapi import FastAPI, Path
from typing_extensions import Annotated

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get")], q: str
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

数値検証: 以上

QueryPath(および後で説明するその他)を使用すると、数値の制約を宣言できます。

ここで、ge=1を使用すると、item_id1「以g上」の整数である必要があります。

from typing import Annotated

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get", ge=1)], q: str
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
from fastapi import FastAPI, Path
from typing_extensions import Annotated

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get", ge=1)], q: str
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

ヒント

可能であれば、Annotatedバージョンを使用することをお勧めします。

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    *, item_id: int = Path(title="The ID of the item to get", ge=1), q: str
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

数値検証: より大きく、以下

以下の場合も同様です

  • gt: よgtり大きい
  • le: 以le
from typing import Annotated

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get", gt=0, le=1000)],
    q: str,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
from fastapi import FastAPI, Path
from typing_extensions import Annotated

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get", gt=0, le=1000)],
    q: str,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

ヒント

可能であれば、Annotatedバージョンを使用することをお勧めします。

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    *,
    item_id: int = Path(title="The ID of the item to get", gt=0, le=1000),
    q: str,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

数値検証: 浮動小数点数、より大きく、より小さい

数値検証は、float値にも有効です。

ここでは、geだけでなく、gtを宣言できることが重要になります。 例えば、値が1未満であっても、0より大きい必要があることを要求できます。

そのため、0.5は有効な値です。 ただし、0.0または0は無効です。

ltも同様です。

from typing import Annotated

from fastapi import FastAPI, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    *,
    item_id: Annotated[int, Path(title="The ID of the item to get", ge=0, le=1000)],
    q: str,
    size: Annotated[float, Query(gt=0, lt=10.5)],
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    if size:
        results.update({"size": size})
    return results
from fastapi import FastAPI, Path, Query
from typing_extensions import Annotated

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    *,
    item_id: Annotated[int, Path(title="The ID of the item to get", ge=0, le=1000)],
    q: str,
    size: Annotated[float, Query(gt=0, lt=10.5)],
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    if size:
        results.update({"size": size})
    return results

ヒント

可能であれば、Annotatedバージョンを使用することをお勧めします。

from fastapi import FastAPI, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    *,
    item_id: int = Path(title="The ID of the item to get", ge=0, le=1000),
    q: str,
    size: float = Query(gt=0, lt=10.5),
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    if size:
        results.update({"size": size})
    return results

要約

QueryPath(およびまだ見ていないその他)を使用すると、クエリパラメータと文字列検証と同じ方法でメタデータと文字列検証を宣言できます。

また、数値検証を宣言することもできます

  • gt: よgtり大きい
  • ge: 以ge
  • lt: よltり小さい
  • le: 以le

情報

QueryPath、および後で説明するその他のクラスは、共通のParamクラスのサブクラスです。

これらはすべて、追加の検証とメタデータに使用されるパラメータを共有しています。

「技術的な詳細」

fastapiからQueryPathなどをインポートすると、実際には関数です。

呼び出されると、同じ名前のクラスのインスタンスが返されます。

そのため、関数であるQueryをインポートします。 そして、それを呼び出すと、同じくQueryという名前のクラスのインスタンスが返されます。

これらの関数は、エディターが型のエラーをマークしないようにするために存在します(クラスを直接使用する代わりに)。

こうすることで、エラーを無視するためのカスタム設定を追加することなく、通常のエディターとコーディングツールを使用できます。