コンテンツにスキップ

リクエストボディ

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

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

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

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

情報

データを送信するには、POST(より一般的)、PUTDELETE、または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
}

...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 Schema定義が生成されます。プロジェクトにとって意味がある場合は、他の場所でも使用できます。
  • これらのスキーマは、生成されたOpenAPIスキーマの一部となり、自動ドキュメントUIで使用されます。

自動ドキュメント

モデルのJSONスキーマは、生成されたOpenAPIスキーマの一部となり、インタラクティブなAPIドキュメントに表示されます。

また、APIドキュメント内の、それらを必要とする各パス操作でも使用されます。

エディタサポート

エディタでは、関数内で、あらゆる場所で型ヒントと補完が得られます(Pydanticモデルではなくdictを受け取った場合は、これは起こりません)。

また、不正な型操作に対するエラーチェックも受けられます。

これは偶然ではなく、フレームワーク全体がこの設計を中心に構築されています。

また、すべての実装の前に、設計段階で徹底的にテストされ、すべて のエディタで動作することが確認されています。

これをサポートするために、Pydantic自体にもいくつかの変更が加えられました。

前のスクリーンショットは、Visual Studio Codeで撮影されました。

しかし、PyCharmや他のほとんどのPythonエディタでも、同じエディタサポートが得られます。

ヒント

エディタとしてPyCharmを使用する場合は、Pydantic PyCharmプラグインを使用できます。

これは、以下の機能により、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:
        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:
        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

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

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

注意

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

str | None (Python 3.10+) または Union in Union[str, None] (Python 3.8+) は、FastAPIによって値が必須ではないと判断するために使用されるわけではなく、デフォルト値が= Noneであるため、必須ではないと判断されます。

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

Pydanticなし

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