クエリパラメータと文字列の検証¶
FastAPI ではパラメータの追加情報とバリデーションを宣言することができます。
以下のアプリケーションを例にしてみましょう:
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/")
async def read_items(q: Union[str, None] = None):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
クエリパラメータ q
は Optional[str]
型で、None
を許容する str
型を意味しており、デフォルトは None
です。そのため、FastAPIはそれが必須ではないと理解します。
備考
FastAPIは、 q
はデフォルト値が =None
であるため、必須ではないと理解します。
Optional[str]
における Optional
はFastAPIには利用されませんが、エディターによるより良いサポートとエラー検出を可能にします。
バリデーションの追加¶
q
はオプショナルですが、もし値が渡されてきた場合には、50文字を超えないことを強制してみましょう。
Query
のインポート¶
そのために、まずはfastapi
からQuery
をインポートします:
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Union[str, None] = Query(default=None, max_length=50)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
デフォルト値としてQuery
を使用¶
パラメータのデフォルト値として使用し、パラメータmax_length
を50に設定します:
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Union[str, None] = Query(default=None, max_length=50)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
デフォルト値None
をQuery(default=None)
に置き換える必要があるので、Query
の最初の引数はデフォルト値を定義するのと同じです。
なので:
q: Optional[str] = Query(default=None)
...を以下と同じようにパラメータをオプションにします:
q: Optional[str] = None
しかし、これはクエリパラメータとして明示的に宣言しています。
情報
FastAPIは以下の部分を気にすることを覚えておいてください:
= None
もしくは:
= Query(default=None)
そして、 None
を利用することでクエリパラメータが必須ではないと検知します。
Optional
の部分は、エディターによるより良いサポートを可能にします。
そして、さらに多くのパラメータをQuery
に渡すことができます。この場合、文字列に適用される、max_length
パラメータを指定します。
q: Union[str, None] = Query(default=None, max_length=50)
これにより、データを検証し、データが有効でない場合は明確なエラーを表示し、OpenAPIスキーマの path operation にパラメータを記載します。
バリデーションをさらに追加する¶
パラメータmin_length
も追加することができます:
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Union[str, None] = Query(default=None, min_length=3, max_length=50),
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
正規表現の追加¶
パラメータが一致するべき正規表現を定義することができます:
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Union[str, None] = Query(
default=None, min_length=3, max_length=50, pattern="^fixedquery$"
),
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
この特定の正規表現は受け取ったパラメータの値をチェックします:
^
: は、これ以降の文字で始まり、これより以前には文字はありません。fixedquery
: は、正確なfixedquery
を持っています.$
: で終わる場合、fixedquery
以降には文字はありません.
もしこれらすべての 正規表現のアイデアについて迷っていても、心配しないでください。多くの人にとって難しい話題です。正規表現を必要としなくても、まだ、多くのことができます。
しかし、あなたがそれらを必要とし、学ぶときにはすでに、 FastAPIで直接それらを使用することができます。
デフォルト値¶
第一引数にNone
を渡して、デフォルト値として使用するのと同じように、他の値を渡すこともできます。
クエリパラメータq
のmin_length
を3
とし、デフォルト値をfixedquery
としてみましょう:
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: str = Query(default="fixedquery", min_length=3)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
備考
デフォルト値を指定すると、パラメータは任意になります。
必須にする¶
これ以上、バリデーションやメタデータを宣言する必要のない場合は、デフォルト値を指定しないだけでクエリパラメータq
を必須にすることができます。以下のように:
q: str
以下の代わりに:
q: Union[str, None] = None
現在は以下の例のようにQuery
で宣言しています:
q: Union[str, None] = Query(default=None, min_length=3)
そのため、Query
を使用して必須の値を宣言する必要がある場合は、第一引数に...
を使用することができます:
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: str = Query(min_length=3)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
情報
これまで...
を見たことがない方へ: これは特殊な単一値です。Pythonの一部であり、"Ellipsis"と呼ばれています。
これは FastAPI にこのパラメータが必須であることを知らせます。
クエリパラメータのリスト / 複数の値¶
クエリパラメータを明示的にQuery
で宣言した場合、値のリストを受け取るように宣言したり、複数の値を受け取るように宣言したりすることもできます。
例えば、URL内に複数回出現するクエリパラメータq
を宣言するには以下のように書きます:
from typing import List, Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Union[List[str], None] = Query(default=None)):
query_items = {"q": q}
return query_items
そしてURLは以下です:
http://localhost:8000/items/?q=foo&q=bar
複数のクエリパラメータの値q
(foo
とbar
)をpath operation関数内で関数パラメータq
としてPythonのlist
を受け取ることになります。
そのため、このURLのレスポンスは以下のようになります:
{
"q": [
"foo",
"bar"
]
}
豆知識
上述の例のように、list
型のクエリパラメータを宣言するには明示的にQuery
を使用する必要があります。そうしない場合、リクエストボディと解釈されます。
対話的APIドキュメントは複数の値を許可するために自動的に更新されます。
デフォルト値を持つ、クエリパラメータのリスト / 複数の値¶
また、値が指定されていない場合はデフォルトのlist
を定義することもできます。
from typing import List
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: List[str] = Query(default=["foo", "bar"])):
query_items = {"q": q}
return query_items
以下のURLを開くと:
http://localhost:8000/items/
q
のデフォルトは: ["foo", "bar"]
となり、レスポンスは以下のようになります:
{
"q": [
"foo",
"bar"
]
}
list
を使う¶
List[str]
の代わりに直接list
を使うこともできます:
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: list = Query(default=[])):
query_items = {"q": q}
return query_items
備考
この場合、FastAPIはリストの内容をチェックしないことを覚えておいてください。
例えばList[int]
はリストの内容が整数であるかどうかをチェックします(そして、文書化します)。しかしlist
だけではそうしません。
より多くのメタデータを宣言する¶
パラメータに関する情報をさらに追加することができます。
その情報は、生成されたOpenAPIに含まれ、ドキュメントのユーザーインターフェースや外部のツールで使用されます。
備考
ツールによってOpenAPIのサポートのレベルが異なる可能性があることを覚えておいてください。
その中には、宣言されたすべての追加情報が表示されていないものもあるかもしれませんが、ほとんどの場合、不足している機能はすでに開発の計画がされています。
title
を追加できます:
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Union[str, None] = Query(default=None, title="Query string", min_length=3),
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
description
を追加できます:
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Union[str, None] = Query(
default=None,
title="Query string",
description="Query string for the items to search in the database that have a good match",
min_length=3,
),
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
エイリアスパラメータ¶
パラメータにitem-query
を指定するとします.
以下のような感じです:
http://127.0.0.1:8000/items/?item-query=foobaritems
しかし、item-query
は有効なPythonの変数名ではありません。
最も近いのはitem_query
でしょう。
しかし、どうしてもitem-query
と正確に一致している必要があるとします...
それならば、alias
を宣言することができます。エイリアスはパラメータの値を見つけるのに使用されます:
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Union[str, None] = Query(default=None, alias="item-query")):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
非推奨パラメータ¶
さて、このパラメータが気に入らなくなったとしましょう
それを使っているクライアントがいるので、しばらくは残しておく必要がありますが、ドキュメントには非推奨と明記しておきたいです。
その場合、Query
にパラメータdeprecated=True
を渡します:
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Union[str, None] = Query(
default=None,
alias="item-query",
title="Query string",
description="Query string for the items to search in the database that have a good match",
min_length=3,
max_length=50,
pattern="^fixedquery$",
deprecated=True,
),
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
ドキュメントは以下のようになります:
まとめ¶
パラメータに追加のバリデーションとメタデータを宣言することができます。
一般的なバリデーションとメタデータ:
alias
title
description
deprecated
文字列のためのバリデーション:
min_length
max_length
regex
この例では、str
の値のバリデーションを宣言する方法を見てきました。
数値のような他の型のバリデーションを宣言する方法は次の章を参照してください。