パスパラメータと数値の検証¶
🌐 Translation by AI and humans
This translation was made by AI guided by humans. 🤝
It could have mistakes of misunderstanding the original meaning, or looking unnatural, etc. 🤖
You can improve this translation by helping us guide the AI LLM better.
クエリパラメータに対してQueryでより多くのバリデーションとメタデータを宣言できるのと同じように、パスパラメータに対してもPathで同じ種類のバリデーションとメタデータを宣言することができます。
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
🤓 Other versions and variants
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
Tip
Prefer to use the Annotated version if possible.
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
Tip
Prefer to use the Annotated version if possible.
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_idに対してtitleのメタデータを宣言するには以下のようにします:
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
🤓 Other versions and variants
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
Tip
Prefer to use the Annotated version if possible.
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
Tip
Prefer to use the Annotated version if possible.
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
備考
パスパラメータはパスの一部でなければならないので、常に必須です。Noneで宣言したりデフォルト値を設定したりしても何も影響せず、常に必須のままです。
必要に応じてパラメータを並び替える¶
豆知識
Annotatedを使う場合、これはおそらくそれほど重要でも必要でもありません。
クエリパラメータqを必須のstrとして宣言したいとしましょう。
また、このパラメータには何も宣言する必要がないので、Queryを使う必要はありません。
しかし、パスパラメータitem_idのためにPathを使用する必要があります。そして何らかの理由でAnnotatedを使いたくないとします。
Pythonは「デフォルト」を持つ値を「デフォルト」を持たない値の前に置くとエラーになります。
しかし、それらを並び替えることができ、デフォルト値を持たない値(クエリパラメータq)を最初に持つことができます。
FastAPIでは関係ありません。パラメータは名前、型、デフォルトの宣言(Query、Pathなど)で検出され、順番は気にしません。
そのため、以下のように関数を宣言することができます:
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
🤓 Other versions and variants
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
ただし、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
🤓 Other versions and variants
Tip
Prefer to use the Annotated version if possible.
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を使う場合、これはおそらくそれほど重要でも必要でもありません。
これは小さなトリックで、便利な場合がありますが、頻繁に必要になることはありません。
次のことをしたい場合:
qクエリパラメータをQueryもデフォルト値もなしで宣言する- パスパラメータ
item_idをPathを使って宣言する - それらを別の順番にする
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
🤓 Other versions and variants
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
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
🤓 Other versions and variants
Tip
Prefer to use the Annotated version if possible.
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
数値の検証: 以上¶
QueryとPath(、そして後述する他のもの)を用いて、数値の制約を宣言できます。
ここで、ge=1の場合、item_idは1「より大きいgか、同じe」整数でなければなりません。
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
🤓 Other versions and variants
Tip
Prefer to use the Annotated version if possible.
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:greaterthanle:less than orequal
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
🤓 Other versions and variants
Tip
Prefer to use the Annotated version if possible.
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の値に対しても有効です。
ここで重要になってくるのはgtだけでなくgeも宣言できることです。これと同様に、例えば、値が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
🤓 Other versions and variants
Tip
Prefer to use the Annotated version if possible.
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
まとめ¶
QueryとPath(そしてまだ見たことない他のもの)では、クエリパラメータと文字列の検証と同じようにメタデータと文字列の検証を宣言することができます。
また、数値のバリデーションを宣言することもできます:
gt:greaterthange:greater than orequallt:lessthanle:less than orequal
情報
Query、Path、および後で見る他のクラスは、共通のParamクラスのサブクラスです。
それらはすべて、これまで見てきた追加のバリデーションとメタデータの同じパラメータを共有しています。
技術詳細
fastapiからQuery、Pathなどをインポートすると、これらは実際には関数です。
呼び出されると、同じ名前のクラスのインスタンスを返します。
そのため、関数であるQueryをインポートし、それを呼び出すと、Queryという名前のクラスのインスタンスが返されます。
これらの関数は(クラスを直接使うのではなく)エディタが型についてエラーとしないようにするために存在します。
この方法によって、これらのエラーを無視するための設定を追加することなく、通常のエディタやコーディングツールを使用することができます。