コンテンツへスキップ

リクエストボディ

クライアント(ブラウザなど)からAPIにデータを送信する必要がある場合、そのデータをリクエストボディとして送信します。

リクエストボディはクライアントからAPIに送信されるデータです。レスポンスボディはAPIがクライアントに送信するデータです。

APIはほとんどの場合、レスポンスボディを送信する必要があります。しかし、クライアントは常にリクエストボディを送信する必要があるわけではありません。時にはパスのみを要求し、クエリパラメーターをいくつか指定するだけで、ボディを送信しないこともあります。

リクエストボディを宣言するには、Pydanticモデルとそのすべての機能と利点を使用します。

情報

データを送信するには、POST(最も一般的)、PUTDELETEPATCHのいずれかを使用する必要があります。

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
}

...descriptiontaxはオプション(デフォルト値は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スキーマ定義を生成します。プロジェクトにとって意味がある場合は、他の場所でも使用できます。
  • これらのスキーマは生成された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

情報

Pydantic v1 ではメソッドは .dict() と呼ばれていましたが、Pydantic v2 では非推奨 (ただし引き続きサポートされています) となり、.model_dump() に改名されました。

ここでの例は Pydantic v1 との互換性のために .dict() を使用していますが、Pydantic v2 を使用できる場合は代わりに .model_dump() を使用してください。

リクエストボディ + パスパラメーター

パスパラメーターとリクエストボディを同時に宣言できます。

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

関数パラメーターは次のように認識されます。

  • パラメーターがパスでも宣言されている場合、それはパスパラメーターとして使用されます。
  • パラメーターが単一型intfloatstrboolなど)の場合、それはクエリパラメーターとして解釈されます。
  • パラメーターがPydanticモデルの型として宣言されている場合、それはリクエストボディとして解釈されます。

Note

FastAPIは、デフォルト値= Noneがあるため、qの値が必須ではないことを認識します。

str | None(Python 3.10+)またはUnionUnion[str, None]、Python 3.8+)は、値が必須ではないことをFastAPIが判断するために使用されるものではありません。FastAPIは、デフォルト値が= Noneであるため、必須ではないことを認識します。

しかし、型アノテーションを追加することで、エディターがより良いサポートを提供し、エラーを検出できるようになります。

Pydanticなし

Pydanticモデルを使用しない場合でも、Bodyパラメーターを使用できます。ボディ - 複数のパラメーター: ボディ内の単一値のドキュメントを参照してください。