クエリパラメータモデル¶
AI coding agents
Use the official FastAPI skill for your installed version. Install it from your project directory:
uvx library-skills
See Develop with AI.
🌐 AI と人間による翻訳
この翻訳は、人間のガイドに基づいて AI によって作成されました。🤝
原文の意図を取り違えていたり、不自然な表現になっている可能性があります。🤖
AI LLM をより適切に誘導するのを手伝う ことで、この翻訳を改善できます。
もし関連する複数のクエリパラメータから成るグループがあるなら、それらを宣言するために、Pydanticモデルを作成できます。
こうすることで、複数の場所でそのモデルを再利用でき、バリデーションやメタデータを、すべてのパラメータに対して一度に宣言できます。😎
備考
この機能は、FastAPIのバージョン 0.115.0 からサポートされています。🤓
Pydanticモデルを使ったクエリパラメータ¶
必要なクエリパラメータをPydanticモデルで宣言し、さらに、そのパラメータを Query として宣言しましょう:
from typing import Annotated, Literal
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field
app = FastAPI()
class FilterParams(BaseModel):
limit: int = Field(100, gt=0, le=100)
offset: int = Field(0, ge=0)
order_by: Literal["created_at", "updated_at"] = "created_at"
tags: list[str] = []
@app.get("/items/")
async def read_items(filter_query: Annotated[FilterParams, Query()]):
return filter_query
🤓 Other versions and variants
Tip
Prefer to use the Annotated version if possible.
from typing import Literal
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field
app = FastAPI()
class FilterParams(BaseModel):
limit: int = Field(100, gt=0, le=100)
offset: int = Field(0, ge=0)
order_by: Literal["created_at", "updated_at"] = "created_at"
tags: list[str] = []
@app.get("/items/")
async def read_items(filter_query: FilterParams = Query()):
return filter_query
FastAPIは、リクエストのクエリパラメータからそれぞれのフィールドのデータを抽出し、定義したPydanticモデルを提供します。
ドキュメントの確認¶
対話的APIドキュメント /docs でクエリパラメータを確認できます:
余分なクエリパラメータを禁止する¶
特定の(あまり一般的ではないかもしれない)ユースケースで、受け取りたいクエリパラメータを制限したい場合があります。
Pydanticのモデル設定を使って、あらゆる extra フィールドを forbid にできます。
from typing import Annotated, Literal
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field
app = FastAPI()
class FilterParams(BaseModel):
model_config = {"extra": "forbid"}
limit: int = Field(100, gt=0, le=100)
offset: int = Field(0, ge=0)
order_by: Literal["created_at", "updated_at"] = "created_at"
tags: list[str] = []
@app.get("/items/")
async def read_items(filter_query: Annotated[FilterParams, Query()]):
return filter_query
🤓 Other versions and variants
Tip
Prefer to use the Annotated version if possible.
from typing import Literal
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field
app = FastAPI()
class FilterParams(BaseModel):
model_config = {"extra": "forbid"}
limit: int = Field(100, gt=0, le=100)
offset: int = Field(0, ge=0)
order_by: Literal["created_at", "updated_at"] = "created_at"
tags: list[str] = []
@app.get("/items/")
async def read_items(filter_query: FilterParams = Query()):
return filter_query
もしクライアントがクエリパラメータとして余分なデータを送ろうとすると、エラーレスポンスが返されます。
例えば、クライアントがクエリパラメータ tool に、値 plumbus を設定して送ろうとすると:
https://example.com/items/?limit=10&tool=plumbus
クエリパラメータ tool が許可されていないことを伝えるエラーレスポンスが返されます。
{
"detail": [
{
"type": "extra_forbidden",
"loc": ["query", "tool"],
"msg": "Extra inputs are not permitted",
"input": "plumbus"
}
]
}
パラメータモデルの組み合わせ¶
複数のクエリパラメータモデルを宣言し、個別のクエリパラメータや依存関係と組み合わせることができます。
from typing import Annotated
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field
app = FastAPI()
class Pagination(BaseModel):
limit: int = Field(10, ge=1)
offset: int = Field(0, ge=0)
class Filters(BaseModel):
tags: list[str] = []
@app.get("/items/")
def read_items(
pagination: Annotated[Pagination, Query()],
filters: Annotated[Filters, Query()],
search: str | None = None,
):
return {"pagination": pagination, "filters": filters, "search": search}
🤓 Other versions and variants
Tip
Prefer to use the Annotated version if possible.
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field
app = FastAPI()
class Pagination(BaseModel):
limit: int = Field(10, ge=1)
offset: int = Field(0, ge=0)
class Filters(BaseModel):
tags: list[str] = []
@app.get("/items/")
def read_items(
pagination: Pagination = Query(),
filters: Filters = Query(),
search: str | None = None,
):
return {"pagination": pagination, "filters": filters, "search": search}
リクエストパラメータは同じ階層のままです。
https://example.com/items/?limit=5&offset=10&tags=red&tags=blue&search=shirt
クエリ文字列に pagination や filters キーはありません。各モデルは、それぞれのデフォルト値、フィールドバリデータ、モデルバリデータを使って、クエリパラメータを独立して検証します。モデルや個別のパラメータを依存関係で宣言した場合も同様です。
複数のモデルがパラメータ名やエイリアスを共有している場合、各モデルはそのリクエストパラメータを独立して検証します。独立した値には、異なる名前やエイリアスを使用してください。OpenAPIでは、依存関係と共有するパラメータと同様に、共有パラメータは一度だけ記載されるため、共有する宣言では同じ型と制約を記述する必要があります。
各モデルの extra 設定は、他のモデルや依存関係で宣言されたものも含め、すべてのクエリパラメータに適用されます。extra="forbid" の場合、そのモデルに含まれないパラメータはすべて拒否されます。extra="allow" の場合、それらのパラメータはモデルの余分なフィールドとして含まれます。
これは Header モデルと Cookie モデルでも機能します。
任意のクエリパラメータモデル¶
クエリパラメータモデルに | None とデフォルト値 None を指定して宣言すると、そのグループを任意にできます。
from datetime import date
from typing import Annotated
from fastapi import FastAPI, Query
from pydantic import BaseModel
app = FastAPI()
class DateRange(BaseModel):
start: date
end: date
@app.get("/items/")
async def read_items(
limit: int = 10,
date_range: Annotated[DateRange | None, Query()] = None,
):
return {"limit": limit, "date_range": date_range}
🤓 Other versions and variants
Tip
Prefer to use the Annotated version if possible.
from datetime import date
from fastapi import FastAPI, Query
from pydantic import BaseModel
app = FastAPI()
class DateRange(BaseModel):
start: date
end: date
@app.get("/items/")
async def read_items(
limit: int = 10,
date_range: DateRange | None = Query(default=None),
):
return {"limit": limit, "date_range": date_range}
start も end も送信されない場合、date_range は None になります。どちらかが送信された場合、FastAPIはモデルを検証し、両方のフィールドを必須とします。
デフォルト値なしで | None を使用した場合、パラメータは引き続き必須です。
余分なパラメータはモデルの extra 設定に従います。無視される余分なパラメータがあっても、モデルが存在するとはみなされません。
OpenAPIでは、グループのフィールドが個別に記載され、任意としてマークされます。
任意のヘッダーパラメータモデルやクッキーパラメータモデルも宣言できます。
まとめ¶
FastAPIでは、クエリパラメータを宣言するために、Pydanticモデルを使用できます。😎
豆知識
ネタバレ注意: Pydanticモデルはクッキーやヘッダーの宣言にも使用できますが、その内容については後のチュートリアルで学びます。🤫