はじめに
FastAPI Souce: https://github.com/tiangolo/fastapi
FastAPI Document: https://fastapi.tiangolo.com
FastAPIチュートリアルのメモ。
基本的にはFastAPIの公式チュートリアルを参考にしていますが、自身の学習のため一部分を省略したり順番を前後させています。
正しい詳細な情報は公式ドキュメントを参考いただければと思います。
Web & Python 初心者かつ翻訳はGoogleとDeepL頼りのため、間違い等ありましたらご指摘いただけますと幸いです。
以前までのメモはこちら
開発環境
Ubuntu 20.04 LTS
Python 3.8.2
pipenv 2018.11.26
目標
- FastAPIにおけるQuery Parameterの使い方を把握する
手順
Intro
前回( FastAPI Tutorialメモ その2 Path Parameters )、関数のパラメータとしてPathパラメータを渡す方法について学習しました。
今回はQueryパラメータを渡す方法について学習したいと思います。
FastAPIでは、Pathパラメータではないパラメータを関数の引数として宣言した場合、自動的にQueryパラメータとして解釈されます。
下記のコードを確認してください。
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): # <- Queryパラメータを指定している。
return fake_items_db[skip : skip + limit]
HTTPのURIにおいてクエリは基本的に?
の後に続くキー
と値
のペアを=
でつなげて表現されます。
複数指定する場合は&
でURIを区切ります。
上記のコードに合わせるのであれば、たとえば下記のようなURLが想定されます:
http://127.0.0.1:8000/items/?skip=0&limit=10
この場合のQueryパラメータは、
- 値が
0
のskip
- 値が
10
のlimit
の2つが関数に渡されます。
これらはURLの一部であるため、通常は文字列(str
)として解釈されるはずです。
しかし、上記のコードでは引数にパラメータを指定する際、Pythonの型であるint
型で宣言したため、パラメータはint
型への変換と検証が行われます。
これは、Pathパラメータで適用された以下の利点がQueryパラメータにも適用されることを意味しています。
- エディタによるサポート
- データの "parsing" (解析)
- データの検証
- 自動ドキュメンテーション
なお、これらの利点はPath、Queryに限らずFastAPIが扱う様々なパラメータでサポートされています。
Defaults (デフォルト値)
QueryパラメータはURIのパスで固定されているわけではなく、オプション設定であるため、デフォルト値を指定することが可能です。
先述のコードでは、デフォルト値としてskip=0
とlimit=10
が指定されていることが確認できます。
よって、このようなURL:
http://127.0.0.1:8000/items/
にブラウザからアクセスした場合、
http://127.0.0.1:8000/items/?skip=0&limit=10
上記2つのURLは同じ出力になります。
また、例えば下記のようなURL:
http://127.0.0.1:8000/items/?skip=20
にアクセスした場合、関数のパラメータは次のようになります:
- URLで設定された
skip=20
- デフォルト値
limit=10
Optional parameters
デフォルト値をNone
とすることにより、オプションとして使用することができるQueryパラメータを宣言することも可能です。
例として、下記のコードを確認してください。
from typing import Optional # typingパッケージからOptionalをインポート
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: str, q: Optional[str] = None): # Queryパラメータ"q"をオプションパラメータとして宣言
if q:
return {"item_id": item_id, "q": q}
return {"item_id": item_id}
この場合、関数のパラメータq
はオプション扱いとなり、デフォルトではNone
として扱われます。
この際にFastAPIがitem_id
がPathパラメータであり、q
がPathパラメータではなくQueryパラメータであることを理解している点に注目してください。
また、FastAPIでは=None
が宣言されるだけでq
がオプションのパラメータであることを認識しています。
Optional
はFastAPI自体が使用しているわけではありません。
わざわざOptional[str]
としてオプションであることを明示しているのは、エディターのサポートによってエラーを事前に発見することができるためです。
Query parameter type conversion (Queryパラメータの型の変換)
Queryパラメータとしてbool
型を宣言することができ、その場合、パラメータはFastAPIによって適した形に変換されれます。
例として、下記のコードを確認してください。
from typing import Optional
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
# 引数のクエリパラメータにbool型を指定している
async def read_item(item_id: str, q: Optional[str] = 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
これらのURLの場合、パラメータshort
はすべてbool値
でTrue
として扱われます。(最初の文字を小文字から大文字にした場合でも同様です)
上記以外の値の場合はFalse
となります。
このように、Queryパラメータにbool型
を指定した場合はFastAPIによる変換が行われます。
Multiple path and query parameters (複数のPathパラメータとQueryパラメータ)
FastAPIでは関数の引数に複数のPathパラメータとQueryパラメータを同時に宣言しても問題なく動作します。
また、それらを特定の順序に従って宣言する必要もありません。
FastAPIでは、パラメータを名前によって認識しているためです。
たとえば、このようなコードがあるとします:
from typing import Optional
from fastapi import FastAPI
app = FastAPI()
@app.get("/users/{user_id}/items/{item_id}") # <- {user_id}と{item_id}をPathパラメータとして指定
async def read_user_item(
user_id: int, item_id: str, q: Optional[str] = None, short: bool = False # <- Pathパラメータではない"q"と"short"はQueryパラメータとして扱う
):
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
この場合、関数の引数の順序を入れ替えたとしても問題ありません。
FastAPIはあくまでもパラメータの名前を基準にして各パラメータを認識します。
Required query parameters (必須のクエリパラメータの指定)
Path以外のパラメータ(現時点ではQueryパラメータしか学習していませんが)でデフォルト値を宣言した場合、そのパラメータは省略不可の必須のパラメータではなくなります。
パラメータを省略した場合はデフォルト値が指定されるためです。
また、デフォルト値をNone
とすることで、特定の値を追加せずにパラメータを任意のオプションパラメータとして宣言することもできます。
では、Queryパラメータを省略不可能な必須のパラメータとして設定したい時はどうするかというと、デフォルト値を宣言しないことで実現できます。
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_user_item(item_id: str, needy: str): # <- デフォルト値を指定せずにパラメータneedyを宣言している
item = {"item_id": item_id, "needy": needy}
return item
上記のneedy
パラメータは必須のstr
型Queryパラメータとして宣言されています。
もしあなたがこのようなURL:
http://127.0.0.1:8000/items/foo-item
をブラウザで開いた場合、必須パラメータであるneedy
が追加されていないため、次のようなエラーが表示されるdでしょう。
{
"detail": [
{
"loc": [
"query",
"needy"
],
"msg": "field required",
"type": "value_error.missing"
}
]
}
needy
は必須のパラメータなので、下記のようにURLで指定する必要があります:
http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
このURLは次のように表示されます:
{
"item_id": "foo-item",
"needy": "sooooneedy"
}
もちろん、必須のパラメータとデフォルト値を持つパラメータとオプションのパラメータを同時に定義することも可能です。
from typing import Optional
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: Optional[int] = None # <-
):
item = {"item_id": item_id, "needy": needy, "skip": skip, "limit": limit}
return item
上記のコードでは、3つのクエリパラメータが宣言されています。
-
needy
:str
型で(デフォルト値を持たない)必須のパラメータ -
skip
:int
型でデフォルト値0
のパラメータ -
limit
:int
型でオプションのパラメータ
なお、Pathパラメータと同様にQueryパラメータでもEnum
を使用することができます。
詳細はPath Parametersを確認ください。
終わりに
今回はQueryパラメータの使用方法を学習しました。
この記事で使用したコードはすべて公式ドキュメント からの引用になりますが、
私のローカル環境で動作することは確認できています。
次回はRequest Body を学習します。