リクエストボディ¶
クライアント (例えばブラウザ) からAPIにデータを送信する必要がある場合、リクエストボディとして送信します。
リクエストボディは、クライアントがAPIに送信するデータです。レスポンスボディは、APIがクライアントに送信するデータです。
APIはほとんどの場合、レスポンスボディを送信する必要があります。しかし、クライアントは常にリクエストボディを送信する必要はありません。パスをリクエストするだけで、クエリパラメーターをいくつか含めることもありますが、ボディを送信しないこともあります。
リクエストボディを宣言するには、Pydanticモデルをそのすべての機能と利点とともに使用します。
情報
データを送信するには、POST
(最も一般的)、PUT
、DELETE
、またはPATCH
のいずれかを使用する必要があります。
GET
リクエストでボディを送信することは、仕様で未定義の動作ですが、FastAPIでは非常に複雑な/極端なユースケースの場合にのみサポートされています。
推奨されないため、Swagger UIでのインタラクティブなドキュメントでは、GET
を使用する場合にボディのドキュメントは表示されず、途中のプロキシがサポートしない可能性があります。
PydanticのBaseModel
をインポートする¶
まず、pydantic
からBaseModel
をインポートする必要があります。
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):
return item
🤓 その他のバージョンとバリアント
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):
return item
データモデルを作成する¶
次に、BaseModel
を継承するクラスとしてデータモデルを宣言します。
すべての属性に標準のPython型を使用します。
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):
return item
🤓 その他のバージョンとバリアント
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):
return item
クエリパラメーターを宣言する場合と同様に、モデル属性にデフォルト値がある場合、それは必須ではありません。そうでない場合、それは必須です。単にオプションにするにはNone
を使用します。
例えば、上記のモデルはJSON "object
" (またはPython dict
) を宣言しています。
{
"name": "Foo",
"description": "An optional description",
"price": 45.2,
"tax": 3.5
}
...description
とtax
はオプション (デフォルト値はNone
) なので、このJSON "object
" も有効です。
{
"name": "Foo",
"price": 45.2
}
パラメーターとして宣言する¶
それをパスオペレーションに追加するには、パスパラメーターやクエリパラメーターを宣言したのと同じ方法で宣言します。
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):
return item
🤓 その他のバージョンとバリアント
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):
return item
...そして、その型を作成したモデルItem
として宣言します。
結果¶
そのPython型の宣言だけで、FastAPIは次のことを行います。
- リクエストのボディをJSONとして読み取ります。
- 対応する型を変換します(必要な場合)。
- データを検証します。
- データが無効な場合、どこで何が不正だったかを正確に示した、明確でわかりやすいエラーを返します。
- 受け取ったデータをパラメーター
item
に提供します。- 関数内で
Item
型として宣言したため、すべての属性とその型について、エディターのサポート(補完など)も利用できます。
- 関数内で
- モデルのJSON Schema定義を生成します。プロジェクトにとって意味がある場合は、他のどこでも使用できます。
- これらのスキーマは、生成されたOpenAPIスキーマの一部となり、自動ドキュメントUIで使用されます。
自動ドキュメント¶
モデルのJSONスキーマは、生成されたOpenAPIスキーマの一部となり、インタラクティブなAPIドキュメントに表示されます。
また、それらを必要とする各パスオペレーション内のAPIドキュメントでも使用されます。
エディターのサポート¶
エディタの関数内で、型ヒントと補完がいたるところで得られます(Pydanticモデルの代わりにdict
を受け取った場合はこれは起こりません)。
不正な型操作に対するエラーチェックも行われます。
これは偶然ではなく、フレームワーク全体がその設計に基づいて構築されています。
また、実装前に設計段階で徹底的にテストされ、すべてのエディタで動作することが確認されています。
これをサポートするために、Pydantic自体にもいくつかの変更が加えられました。
以前のスクリーンショットはVisual Studio Codeで撮影されたものです。
しかし、PyCharmやほとんどの他のPythonエディターでも同じエディターサポートが得られます。
ヒント
エディタとしてPyCharmを使用している場合は、Pydantic PyCharm Pluginを使用できます。
Pydanticモデルのエディタサポートが向上し、以下が提供されます。
- オートコンプリート
- 型チェック
- リファクタリング
- 検索
- 検査
モデルを使用する¶
関数内では、モデルオブジェクトのすべての属性に直接アクセスできます。
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):
item_dict = item.dict()
if item.tax is not None:
price_with_tax = item.price + item.tax
item_dict.update({"price_with_tax": price_with_tax})
return item_dict
🤓 その他のバージョンとバリアント
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):
item_dict = item.dict()
if item.tax is not None:
price_with_tax = item.price + item.tax
item_dict.update({"price_with_tax": price_with_tax})
return item_dict
リクエストボディ + パスパラメーター¶
パスパラメーターとリクエストボディを同時に宣言できます。
FastAPIは、パスパラメーターと一致する関数パラメーターがパスから取得されること、およびPydanticモデルとして宣言された関数パラメーターがリクエストボディから取得されることを認識します。
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
app = FastAPI()
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
return {"item_id": item_id, **item.dict()}
🤓 その他のバージョンとバリアント
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
app = FastAPI()
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
return {"item_id": item_id, **item.dict()}
リクエストボディ + パス + クエリパラメーター¶
同時にボディ、パス、およびクエリパラメータを宣言することもできます。
FastAPIはそれらをそれぞれ認識し、正しい場所からデータを取得します。
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
app = FastAPI()
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item, q: str | None = None):
result = {"item_id": item_id, **item.dict()}
if q:
result.update({"q": q})
return result
🤓 その他のバージョンとバリアント
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
app = FastAPI()
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item, q: Union[str, None] = None):
result = {"item_id": item_id, **item.dict()}
if q:
result.update({"q": q})
return result
関数パラメータは次のように認識されます。
- パラメータがパスでも宣言されている場合、パスパラメータとして使用されます。
- パラメータが単数形型 (
int
,float
,str
,bool
など) の場合、クエリパラメータとして解釈されます。 - パラメータがPydanticモデルの型として宣言されている場合、リクエストボディとして解釈されます。
注
FastAPIは、デフォルト値= None
があるため、q
の値が必須ではないことを認識します。
str | None
(Python 3.10+) またはUnion[str, None]
(Python 3.8+) のUnion
は、FastAPIが値が必須ではないことを判断するために使用されるわけではありません。デフォルト値が= None
であるため、必須ではないことを認識します。
しかし、型アノテーションを追加することで、エディターがより良いサポートを提供し、エラーを検出できるようになります。
Pydanticなし¶
Pydanticモデルを使いたくない場合は、Bodyパラメータを使うこともできます。詳しくはボディ - 複数のパラメータ: ボディ内の単一値のドキュメントを参照してください。