ボディ - ネストされたモデル¶
🌐 Translation by AI and humans
This translation was made by AI guided by humans. 🤝
It could have mistakes of misunderstanding the original meaning, or looking unnatural, etc. 🤖
You can improve this translation by helping us guide the AI LLM better.
FastAPI を使用すると、深くネストされた任意のモデルを定義、検証、文書化、使用することができます(Pydanticのおかげです)。
リストのフィールド¶
属性をサブタイプとして定義することができます。例えば、Pythonのlist:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
tags: list = []
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
🤓 Other versions and variants
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
tags: list = []
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
これにより、各項目の型は宣言されていませんが、tagsはリストになります。
タイプパラメータを持つリストのフィールド¶
しかし、Pythonには内部の型、または「タイプパラメータ」を使ってリストを宣言するための特定の方法があります:
タイプパラメータを持つlistの宣言¶
list、dict、tupleのようにタイプパラメータ(内部の型)を持つ型を宣言するには、
角括弧([と])を使って内部の型を「タイプパラメータ」として渡します。
my_list: list[str]
型宣言の標準的なPythonの構文はこれだけです。
内部の型を持つモデルの属性にも同じ標準の構文を使用してください。
そのため、以下の例ではtagsを具体的な「文字列のリスト」にすることができます:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
tags: list[str] = []
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
🤓 Other versions and variants
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
tags: list[str] = []
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
セット型¶
しかし、よく考えてみると、タグは繰り返すべきではなく、おそらくユニークな文字列になるのではないかと気付いたとします。
そして、Pythonにはユニークな項目のセットのための特別なデータ型setがあります。
そして、tagsを文字列のセットとして宣言できます:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
tags: set[str] = set()
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
🤓 Other versions and variants
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
tags: set[str] = set()
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
これを使えば、データが重複しているリクエストを受けた場合でも、ユニークな項目のセットに変換されます。
そして、そのデータを出力すると、たとえソースに重複があったとしても、固有の項目のセットとして出力されます。
また、それに応じて注釈をつけたり、文書化したりします。
ネストされたモデル¶
Pydanticモデルの各属性には型があります。
しかし、その型はそれ自体が別のPydanticモデルである可能性があります。
そのため、特定の属性名、型、バリデーションを指定して、深くネストしたJSON「オブジェクト」を宣言することができます。
すべては、任意のネストにされています。
サブモデルの定義¶
例えば、Imageモデルを定義することができます:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Image(BaseModel):
url: str
name: str
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
tags: set[str] = set()
image: Image | None = None
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
🤓 Other versions and variants
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Image(BaseModel):
url: str
name: str
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
tags: set[str] = set()
image: Union[Image, None] = None
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
サブモデルを型として使用¶
そして、それを属性の型として使用することができます:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Image(BaseModel):
url: str
name: str
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
tags: set[str] = set()
image: Image | None = None
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
🤓 Other versions and variants
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Image(BaseModel):
url: str
name: str
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
tags: set[str] = set()
image: Union[Image, None] = None
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
これは FastAPI が以下のようなボディを期待することを意味します:
{
"name": "Foo",
"description": "The pretender",
"price": 42.0,
"tax": 3.2,
"tags": ["rock", "metal", "bar"],
"image": {
"url": "http://example.com/baz.jpg",
"name": "The Foo live"
}
}
繰り返しになりますが、FastAPI を使用して、その宣言を行うだけで以下のような恩恵を受けられます:
- ネストされたモデルでも対応可能なエディタのサポート(補完など)
- データ変換
- データの検証
- 自動文書化
特殊な型とバリデーション¶
strやint、floatなどの通常の単数型の他にも、strを継承したより複雑な単数型を使うこともできます。
すべてのオプションをみるには、Pydanticの型の概要を確認してください。次の章でいくつかの例をみることができます。
例えば、Imageモデルのようにurlフィールドがある場合、strの代わりにPydanticのHttpUrlのインスタンスとして宣言することができます:
from fastapi import FastAPI
from pydantic import BaseModel, HttpUrl
app = FastAPI()
class Image(BaseModel):
url: HttpUrl
name: str
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
tags: set[str] = set()
image: Image | None = None
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
🤓 Other versions and variants
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel, HttpUrl
app = FastAPI()
class Image(BaseModel):
url: HttpUrl
name: str
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
tags: set[str] = set()
image: Union[Image, None] = None
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
文字列は有効なURLであることが確認され、そのようにJSON Schema / OpenAPIで文書化されます。
サブモデルのリストを持つ属性¶
Pydanticモデルをlistやsetなどのサブタイプとして使用することもできます:
from fastapi import FastAPI
from pydantic import BaseModel, HttpUrl
app = FastAPI()
class Image(BaseModel):
url: HttpUrl
name: str
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
tags: set[str] = set()
images: list[Image] | None = None
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
🤓 Other versions and variants
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel, HttpUrl
app = FastAPI()
class Image(BaseModel):
url: HttpUrl
name: str
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
tags: set[str] = set()
images: Union[list[Image], None] = None
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
これは、次のようなJSONボディを期待します(変換、検証、ドキュメントなど):
{
"name": "Foo",
"description": "The pretender",
"price": 42.0,
"tax": 3.2,
"tags": [
"rock",
"metal",
"bar"
],
"images": [
{
"url": "http://example.com/baz.jpg",
"name": "The Foo live"
},
{
"url": "http://example.com/dave.jpg",
"name": "The Baz"
}
]
}
情報
imagesキーが画像オブジェクトのリストを持つようになったことに注目してください。
深くネストされたモデル¶
深くネストされた任意のモデルを定義することができます:
from fastapi import FastAPI
from pydantic import BaseModel, HttpUrl
app = FastAPI()
class Image(BaseModel):
url: HttpUrl
name: str
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
tags: set[str] = set()
images: list[Image] | None = None
class Offer(BaseModel):
name: str
description: str | None = None
price: float
items: list[Item]
@app.post("/offers/")
async def create_offer(offer: Offer):
return offer
🤓 Other versions and variants
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel, HttpUrl
app = FastAPI()
class Image(BaseModel):
url: HttpUrl
name: str
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
tags: set[str] = set()
images: Union[list[Image], None] = None
class Offer(BaseModel):
name: str
description: Union[str, None] = None
price: float
items: list[Item]
@app.post("/offers/")
async def create_offer(offer: Offer):
return offer
情報
OfferはItemのリストであり、それらがさらにオプションのImageのリストを持っていることに注目してください。
純粋なリストのボディ¶
期待するJSONボディのトップレベルの値がJSONarray(Pythonのlist)であれば、Pydanticモデルと同じように、関数のパラメータで型を宣言することができます:
images: list[Image]
以下のように:
from fastapi import FastAPI
from pydantic import BaseModel, HttpUrl
app = FastAPI()
class Image(BaseModel):
url: HttpUrl
name: str
@app.post("/images/multiple/")
async def create_multiple_images(images: list[Image]):
return images
あらゆる場所でのエディタサポート¶
そして、あらゆる場所でエディタサポートを得られます。
以下のようにリストの中の項目でも:

Pydanticモデルではなく、dictを直接使用している場合はこのようなエディタのサポートは得られません。
しかし、それらについて心配する必要はありません。入力されたdictは自動的に変換され、出力も自動的にJSONに変換されます。
任意のdictのボディ¶
また、ある型のキーと別の型の値を持つdictとしてボディを宣言することもできます。
この方法で、有効なフィールド/属性名を事前に知る必要がありません(Pydanticモデルの場合のように)。
これは、まだ知らないキーを受け取りたいときに便利です。
もうひとつ便利なケースは、別の型(例: int)のキーを持ちたい場合です。
それをここで見ていきます。
この場合、intのキーとfloatの値を持つものであれば、どんなdictでも受け入れることができます:
from fastapi import FastAPI
app = FastAPI()
@app.post("/index-weights/")
async def create_index_weights(weights: dict[int, float]):
return weights
豆知識
JSONはキーとしてstrしかサポートしていないことに注意してください。
しかしPydanticには自動データ変換機能があります。
これは、APIクライアントがキーとして文字列しか送信できなくても、それらの文字列に純粋な整数が含まれている限り、Pydanticが変換して検証することを意味します。
そして、weightsとして受け取るdictは、実際にはintのキーとfloatの値を持つことになります。
まとめ¶
FastAPI を使用すると、Pydanticモデルが提供する最大限の柔軟性を持ちながら、コードをシンプルに短く、エレガントに保つことができます。
しかし、以下のような利点があります:
- エディタのサポート(どこでも補完!)
- データ変換(別名:構文解析 / シリアライズ)
- データの検証
- スキーマ文書
- 自動ドキュメント