レスポンスモデル - 戻り値の型¶
パス操作関数 の戻り値の型をアノテーションすることで、レスポンスに使用する型を宣言できます。
関数のパラメータで入力データに使用するのと同じ方法で型アノテーションを使用できます。Pydanticモデル、リスト、辞書、整数やブール値などのスカラー値を使用できます。
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.post("/items/")
async def create_item(item: Item) -> Item:
return item
@app.get("/items/")
async def read_items() -> list[Item]:
return [
Item(name="Portal Gun", price=42.0),
Item(name="Plumbus", price=32.0),
]
🤓 その他のバージョンとバリアント
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.post("/items/")
async def create_item(item: Item) -> Item:
return item
@app.get("/items/")
async def read_items() -> list[Item]:
return [
Item(name="Portal Gun", price=42.0),
Item(name="Plumbus", price=32.0),
]
from typing import List, 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.post("/items/")
async def create_item(item: Item) -> Item:
return item
@app.get("/items/")
async def read_items() -> List[Item]:
return [
Item(name="Portal Gun", price=42.0),
Item(name="Plumbus", price=32.0),
]
FastAPI はこの戻り値の型を以下のように使用します。
- 返されたデータを検証します。
- データが無効な場合(例:フィールドが欠落している場合)、それはあなたのアプリコードが壊れていて、あるべきものを返していないことを意味し、不正なデータを返す代わりにサーバーエラーを返します。これにより、あなたとあなたのクライアントは、期待されるデータとデータの形式を受け取ることが保証されます。
- OpenAPI のパス操作にレスポンスのJSON Schemaを追加します。
- これは自動ドキュメントによって使用されます。
- また、自動クライアントコード生成ツールによっても使用されます。
しかし、最も重要なのは
- 出力データを戻り値の型で定義されたものに制限してフィルタリングします。
- これは特にセキュリティにとって重要です。これについては後述します。
response_model
パラメータ¶
型が宣言しているものと全く異なるデータを返す必要がある、またはそうしたい場合があります。
たとえば、辞書やデータベースオブジェクトを返したいが、それをPydanticモデルとして宣言したい場合があります。こうすることで、Pydanticモデルが、返されたオブジェクト(例:辞書やデータベースオブジェクト)のすべてのデータドキュメント、検証などを実行します。
戻り値の型アノテーションを追加した場合、ツールやエディタは、関数が宣言したもの(例:Pydanticモデル)とは異なる型(例:辞書)を返していることを示す(正しい)エラーを表示します。
そのような場合は、戻り値の型の代わりに、パス操作デコレータパラメータの response_model
を使用できます。
response_model
パラメータは、以下のどのパス操作でも使用できます。
@app.get()
@app.post()
@app.put()
@app.delete()
- など
from typing import Any
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.post("/items/", response_model=Item)
async def create_item(item: Item) -> Any:
return item
@app.get("/items/", response_model=list[Item])
async def read_items() -> Any:
return [
{"name": "Portal Gun", "price": 42.0},
{"name": "Plumbus", "price": 32.0},
]
🤓 その他のバージョンとバリアント
from typing import Any, 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.post("/items/", response_model=Item)
async def create_item(item: Item) -> Any:
return item
@app.get("/items/", response_model=list[Item])
async def read_items() -> Any:
return [
{"name": "Portal Gun", "price": 42.0},
{"name": "Plumbus", "price": 32.0},
]
from typing import Any, List, 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.post("/items/", response_model=Item)
async def create_item(item: Item) -> Any:
return item
@app.get("/items/", response_model=List[Item])
async def read_items() -> Any:
return [
{"name": "Portal Gun", "price": 42.0},
{"name": "Plumbus", "price": 32.0},
]
注記
response_model
は、すべてのパラメータやボディとは異なり、「デコレータ」メソッド(get
、post
など)のパラメータであることに注意してください。
response_model
は、Pydanticモデルフィールドに宣言するのと同じ型を受け取ります。したがって、Pydanticモデルであることもありますが、たとえば List[Item]
のようなPydanticモデルのlist
であることもあります。
FastAPI はこの response_model
を使用して、すべてのデータドキュメント、検証などを行い、出力データをその型宣言に変換およびフィルタリングします。
ヒント
エディタ、mypy などで厳密な型チェックを行っている場合は、関数の戻り値の型を Any
として宣言できます。
これにより、意図的に何でも返すことをエディタに伝えます。しかし、FastAPI は引き続き response_model
を使用してデータのドキュメント、検証、フィルタリングなどを行います。
response_model
の優先順位¶
戻り値の型と response_model
の両方を宣言した場合、response_model
が優先され、FastAPI で使用されます。
これにより、応答モデルとは異なる型を返す場合でも、エディタや mypy などのツールで使用するために、関数に正しい型アノテーションを追加できます。それでも、FastAPI で response_model
を使用してデータの検証、ドキュメント化などを実行できます。
また、response_model=None
を使用して、そのパス操作の応答モデルの作成を無効にすることもできます。これは、有効な Pydantic フィールドではないものに対して型アノテーションを追加している場合に必要になることがあります。その例を以下のセクションで示します。
同じ入力データを返す¶
ここでは UserIn
モデルを宣言しています。これにはプレーンテキストのパスワードが含まれます。
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
app = FastAPI()
class UserIn(BaseModel):
username: str
password: str
email: EmailStr
full_name: str | None = None
# Don't do this in production!
@app.post("/user/")
async def create_user(user: UserIn) -> UserIn:
return user
🤓 その他のバージョンとバリアント
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
app = FastAPI()
class UserIn(BaseModel):
username: str
password: str
email: EmailStr
full_name: Union[str, None] = None
# Don't do this in production!
@app.post("/user/")
async def create_user(user: UserIn) -> UserIn:
return user
情報
EmailStr
を使用するには、まず email-validator
をインストールしてください。
仮想環境を作成し、アクティブ化してからインストールしてください。たとえば、
$ pip install email-validator
または
$ pip install "pydantic[email]"
そして、このモデルを入力として宣言し、同じモデルを出力として宣言しています。
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
app = FastAPI()
class UserIn(BaseModel):
username: str
password: str
email: EmailStr
full_name: str | None = None
# Don't do this in production!
@app.post("/user/")
async def create_user(user: UserIn) -> UserIn:
return user
🤓 その他のバージョンとバリアント
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
app = FastAPI()
class UserIn(BaseModel):
username: str
password: str
email: EmailStr
full_name: Union[str, None] = None
# Don't do this in production!
@app.post("/user/")
async def create_user(user: UserIn) -> UserIn:
return user
これで、ブラウザがパスワード付きのユーザーを作成するたびに、API は同じパスワードをレスポンスで返します。
この場合、同じユーザーがパスワードを送信しているので、問題にはならないかもしれません。
しかし、同じモデルを別のパス操作に使用すると、ユーザーのパスワードをすべてのクライアントに送信してしまう可能性があります。
危険
すべての注意点を理解し、何をしているのか分かっている場合を除き、ユーザーのプレーンパスワードを保存したり、このようにレスポンスで送信したりしないでください。
出力モデルを追加する¶
代わりに、平文パスワードを含む入力モデルと、パスワードを含まない出力モデルを作成できます。
from typing import Any
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
app = FastAPI()
class UserIn(BaseModel):
username: str
password: str
email: EmailStr
full_name: str | None = None
class UserOut(BaseModel):
username: str
email: EmailStr
full_name: str | None = None
@app.post("/user/", response_model=UserOut)
async def create_user(user: UserIn) -> Any:
return user
🤓 その他のバージョンとバリアント
from typing import Any, Union
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
app = FastAPI()
class UserIn(BaseModel):
username: str
password: str
email: EmailStr
full_name: Union[str, None] = None
class UserOut(BaseModel):
username: str
email: EmailStr
full_name: Union[str, None] = None
@app.post("/user/", response_model=UserOut)
async def create_user(user: UserIn) -> Any:
return user
ここでは、パス操作関数がパスワードを含む同じ入力ユーザーを返しているにもかかわらず、
from typing import Any
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
app = FastAPI()
class UserIn(BaseModel):
username: str
password: str
email: EmailStr
full_name: str | None = None
class UserOut(BaseModel):
username: str
email: EmailStr
full_name: str | None = None
@app.post("/user/", response_model=UserOut)
async def create_user(user: UserIn) -> Any:
return user
🤓 その他のバージョンとバリアント
from typing import Any, Union
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
app = FastAPI()
class UserIn(BaseModel):
username: str
password: str
email: EmailStr
full_name: Union[str, None] = None
class UserOut(BaseModel):
username: str
email: EmailStr
full_name: Union[str, None] = None
@app.post("/user/", response_model=UserOut)
async def create_user(user: UserIn) -> Any:
return user
... response_model
をパスワードを含まない UserOut
モデルと宣言しました。
from typing import Any
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
app = FastAPI()
class UserIn(BaseModel):
username: str
password: str
email: EmailStr
full_name: str | None = None
class UserOut(BaseModel):
username: str
email: EmailStr
full_name: str | None = None
@app.post("/user/", response_model=UserOut)
async def create_user(user: UserIn) -> Any:
return user
🤓 その他のバージョンとバリアント
from typing import Any, Union
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
app = FastAPI()
class UserIn(BaseModel):
username: str
password: str
email: EmailStr
full_name: Union[str, None] = None
class UserOut(BaseModel):
username: str
email: EmailStr
full_name: Union[str, None] = None
@app.post("/user/", response_model=UserOut)
async def create_user(user: UserIn) -> Any:
return user
そのため、FastAPI は、出力モデル (Pydantic を使用) で宣言されていないすべてのデータをフィルタリングします。
response_model
または戻り値の型¶
この場合、2つのモデルが異なるため、関数の戻り値の型を UserOut
とアノテーションした場合、エディタやツールは、クラスが異なるため無効な型を返していると不平を言います。
そのため、この例では response_model
パラメータで宣言する必要があります。
...しかし、それを克服する方法については以下を読み続けてください。
戻り値の型とデータフィルタリング¶
前の例を続けましょう。関数を1つの型でアノテーションしたいが、関数から実際により多くのデータを含むものを返したい場合です。
FastAPI にレスポンスモデルを使用してデータをフィルタリングし続けてほしいのです。そうすれば、関数がより多くのデータを返したとしても、レスポンスにはレスポンスモデルで宣言されたフィールドのみが含まれます。
前の例では、クラスが異なっていたため、response_model
パラメータを使用する必要がありました。しかし、それは、エディタやツールによる関数の戻り値の型チェックのサポートが得られないことも意味します。
しかし、このようなことをする必要があるほとんどの場合、この例のように、モデルに一部のデータをフィルタリング/削除してほしいだけです。
そのような場合、クラスと継承を使用して関数の型アノテーションを活用し、エディタとツールでより良いサポートを得ながら、FastAPI のデータフィルタリングも利用できます。
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
app = FastAPI()
class BaseUser(BaseModel):
username: str
email: EmailStr
full_name: str | None = None
class UserIn(BaseUser):
password: str
@app.post("/user/")
async def create_user(user: UserIn) -> BaseUser:
return user
🤓 その他のバージョンとバリアント
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
app = FastAPI()
class BaseUser(BaseModel):
username: str
email: EmailStr
full_name: Union[str, None] = None
class UserIn(BaseUser):
password: str
@app.post("/user/")
async def create_user(user: UserIn) -> BaseUser:
return user
これにより、エディタやmypyなどのツールサポートが得られます。このコードは型に関して正しいため、FastAPIのデータフィルタリングも利用できます。
これはどのように機能するのでしょうか?見てみましょう。🤓
型アノテーションとツール¶
まず、エディタ、mypy、その他のツールがこれをどのように認識するか見てみましょう。
BaseUser
には基本フィールドがあります。そして、UserIn
は BaseUser
を継承し、password
フィールドを追加するため、両方のモデルのすべてのフィールドが含まれます。
関数の戻り値の型を BaseUser
とアノテーションしていますが、実際には UserIn
インスタンスを返しています。
エディタ、mypy、その他のツールは、これについて苦情を言いません。なぜなら、型付けの観点から見ると、UserIn
は BaseUser
のサブクラスであり、BaseUser
であるものが期待される場合に有効な型だからです。
FastAPI のデータフィルタリング¶
さて、FastAPI は戻り値の型を確認し、返されるデータがその型で宣言されたフィールドのみを**含む**ことを保証します。
FastAPI は Pydantic とともに内部でいくつかのことを行い、クラス継承の同じルールが返されたデータフィルタリングに使用されないようにします。そうでなければ、予想よりもはるかに多くのデータを返すことになってしまいます。
このようにして、ツールサポートとデータフィルタリングの両方を備えた型アノテーションという、両方の良い点を活用できます。
ドキュメントで確認する¶
自動ドキュメントを見ると、入力モデルと出力モデルの両方に独自のJSON Schemaがあることを確認できます。
そして、両方のモデルがインタラクティブなAPIドキュメントに使用されます。
その他の戻り値の型アノテーション¶
有効な Pydantic フィールドではないものを返し、それを関数でアノテーションする場合があります。これは、ツール (エディタ、mypy など) が提供するサポートを得るためだけに行われます。
レスポンスを直接返す¶
最も一般的なケースは、高度なドキュメントで後述する、レスポンスを直接返すことです。
from fastapi import FastAPI, Response
from fastapi.responses import JSONResponse, RedirectResponse
app = FastAPI()
@app.get("/portal")
async def get_portal(teleport: bool = False) -> Response:
if teleport:
return RedirectResponse(url="https://www.youtube.com/watch?v=dQw4w9WgXcQ")
return JSONResponse(content={"message": "Here's your interdimensional portal."})
この単純なケースは、戻り値の型アノテーションが Response
クラス (またはそのサブクラス) であるため、FastAPI によって自動的に処理されます。
RedirectResponse
と JSONResponse
の両方が Response
のサブクラスであるため、型アノテーションは正しく、ツールも問題なく動作します。
レスポンスサブクラスをアノテーションする¶
型アノテーションで Response
のサブクラスを使用することもできます。
from fastapi import FastAPI
from fastapi.responses import RedirectResponse
app = FastAPI()
@app.get("/teleport")
async def get_teleport() -> RedirectResponse:
return RedirectResponse(url="https://www.youtube.com/watch?v=dQw4w9WgXcQ")
これは RedirectResponse
が Response
のサブクラスであるため機能し、FastAPI はこの単純なケースを自動的に処理します。
無効な戻り値の型アノテーション¶
しかし、有効な Pydantic 型ではない任意のオブジェクト (例: データベースオブジェクト) を返し、関数内でそのようにアノテーションした場合、FastAPI はその型アノテーションから Pydantic レスポンスモデルを作成しようとして失敗します。
有効な Pydantic 型ではない型が1つ以上含まれる複数の型のユニオンがある場合も同様で、例えばこれは失敗します 💥
from fastapi import FastAPI, Response
from fastapi.responses import RedirectResponse
app = FastAPI()
@app.get("/portal")
async def get_portal(teleport: bool = False) -> Response | dict:
if teleport:
return RedirectResponse(url="https://www.youtube.com/watch?v=dQw4w9WgXcQ")
return {"message": "Here's your interdimensional portal."}
🤓 その他のバージョンとバリアント
from typing import Union
from fastapi import FastAPI, Response
from fastapi.responses import RedirectResponse
app = FastAPI()
@app.get("/portal")
async def get_portal(teleport: bool = False) -> Union[Response, dict]:
if teleport:
return RedirectResponse(url="https://www.youtube.com/watch?v=dQw4w9WgXcQ")
return {"message": "Here's your interdimensional portal."}
...これは、型アノテーションが Pydantic 型ではなく、単一の Response
クラスまたはサブクラスでもなく、Response
と dict
のユニオン (どちらか一方) であるため、失敗します。
レスポンスモデルを無効にする¶
上記の例に続き、FastAPI が実行するデフォルトのデータ検証、ドキュメント化、フィルタリングなどを行いたくない場合があります。
しかし、エディタや型チェッカー (例: mypy) のようなツールからのサポートを得るために、関数の戻り値の型アノテーションは保持したい場合があります。
この場合、response_model=None
を設定することで、レスポンスモデルの生成を無効にできます。
from fastapi import FastAPI, Response
from fastapi.responses import RedirectResponse
app = FastAPI()
@app.get("/portal", response_model=None)
async def get_portal(teleport: bool = False) -> Response | dict:
if teleport:
return RedirectResponse(url="https://www.youtube.com/watch?v=dQw4w9WgXcQ")
return {"message": "Here's your interdimensional portal."}
🤓 その他のバージョンとバリアント
from typing import Union
from fastapi import FastAPI, Response
from fastapi.responses import RedirectResponse
app = FastAPI()
@app.get("/portal", response_model=None)
async def get_portal(teleport: bool = False) -> Union[Response, dict]:
if teleport:
return RedirectResponse(url="https://www.youtube.com/watch?v=dQw4w9WgXcQ")
return {"message": "Here's your interdimensional portal."}
これにより、FastAPIはレスポンスモデルの生成をスキップし、FastAPIアプリケーションに影響を与えることなく、必要な戻り値の型アノテーションを持つことができます。🤓
レスポンスモデルのエンコーディングパラメータ¶
応答モデルには、次のようなデフォルト値が含まれる場合があります。
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float = 10.5
tags: list[str] = []
items = {
"foo": {"name": "Foo", "price": 50.2},
"bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
"baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
}
@app.get("/items/{item_id}", response_model=Item, response_model_exclude_unset=True)
async def read_item(item_id: str):
return items[item_id]
🤓 その他のバージョンとバリアント
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: float = 10.5
tags: list[str] = []
items = {
"foo": {"name": "Foo", "price": 50.2},
"bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
"baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
}
@app.get("/items/{item_id}", response_model=Item, response_model_exclude_unset=True)
async def read_item(item_id: str):
return items[item_id]
from typing import List, Union
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: float = 10.5
tags: List[str] = []
items = {
"foo": {"name": "Foo", "price": 50.2},
"bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
"baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
}
@app.get("/items/{item_id}", response_model=Item, response_model_exclude_unset=True)
async def read_item(item_id: str):
return items[item_id]
description: Union[str, None] = None
(または Python 3.10 ではstr | None = None
) は、デフォルトでNone
です。tax: float = 10.5
は、デフォルトで10.5
です。tags: List[str] = []
は、デフォルトで空のリスト[]
です。
ただし、実際に保存されていない場合は、結果から除外したい場合があります。
たとえば、NoSQLデータベースに多くのオプション属性を持つモデルがあるが、デフォルト値でいっぱいの非常に長いJSONレスポンスを送信したくない場合などです。
response_model_exclude_unset
パラメータを使用する¶
パス操作デコレータのパラメータ response_model_exclude_unset=True
を設定できます。
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float = 10.5
tags: list[str] = []
items = {
"foo": {"name": "Foo", "price": 50.2},
"bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
"baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
}
@app.get("/items/{item_id}", response_model=Item, response_model_exclude_unset=True)
async def read_item(item_id: str):
return items[item_id]
🤓 その他のバージョンとバリアント
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: float = 10.5
tags: list[str] = []
items = {
"foo": {"name": "Foo", "price": 50.2},
"bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
"baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
}
@app.get("/items/{item_id}", response_model=Item, response_model_exclude_unset=True)
async def read_item(item_id: str):
return items[item_id]
from typing import List, Union
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: float = 10.5
tags: List[str] = []
items = {
"foo": {"name": "Foo", "price": 50.2},
"bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
"baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
}
@app.get("/items/{item_id}", response_model=Item, response_model_exclude_unset=True)
async def read_item(item_id: str):
return items[item_id]
これにより、デフォルト値はレスポンスに含まれず、実際に設定された値のみが含まれます。
したがって、ID foo
のアイテムに対してそのパス操作にリクエストを送信した場合、レスポンス (デフォルト値を除く) は次のようになります。
{
"name": "Foo",
"price": 50.2
}
情報
Pydantic v1 ではメソッドは .dict()
と呼ばれていましたが、Pydantic v2 では非推奨 (ただし引き続きサポートされています) となり、.model_dump()
に改名されました。
ここでの例は Pydantic v1 との互換性のために .dict()
を使用していますが、Pydantic v2 を使用できる場合は代わりに .model_dump()
を使用してください。
情報
FastAPI は、Pydantic モデルの .dict()
に その exclude_unset
パラメータ を使用してこれを実現します。
情報
以下も使用できます。
response_model_exclude_defaults=True
response_model_exclude_none=True
Pydantic ドキュメントの exclude_defaults
と exclude_none
の説明を参照してください。
デフォルト値を持つフィールドの値を持つデータ¶
しかし、データがID bar
のアイテムのように、デフォルト値を持つモデルのフィールドの値を持っている場合、
{
"name": "Bar",
"description": "The bartenders",
"price": 62,
"tax": 20.2
}
それらはレスポンスに含まれます。
デフォルト値と同じ値を持つデータ¶
データがID baz
のアイテムのように、デフォルト値と同じ値を持っている場合、
{
"name": "Baz",
"description": None,
"price": 50.2,
"tax": 10.5,
"tags": []
}
FastAPI は (実際には Pydantic が) 賢く、description
、tax
、tags
がデフォルト値と同じ値を持っているにもかかわらず、明示的に設定された (デフォルトから取得されたのではなく) と認識します。
そのため、JSONレスポンスに含まれます。
ヒント
デフォルト値は None
だけでなく、何でもよいことに注意してください。
リスト ([]
)、float
の 10.5
などです。
response_model_include
と response_model_exclude
¶
パス操作デコレータパラメータの response_model_include
と response_model_exclude
も使用できます。
これらは、含める (残りを省略する) または除外する (残りをすべて含める) 属性の名前を持つ str
の set
を受け取ります。
これは、Pydantic モデルが1つだけで、出力から一部のデータを削除したい場合の簡単なショートカットとして使用できます。
ヒント
ただし、これらのパラメータを使用するよりも、複数のクラスを使用する上記のアイデアを使用することをお勧めします。
これは、response_model_include
や response_model_exclude
を使用して一部の属性を省略しても、アプリのOpenAPI (およびドキュメント) で生成されるJSON Schemaは、完全なモデルのものになるためです。
これは、同様に機能する response_model_by_alias
にも当てはまります。
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float = 10.5
items = {
"foo": {"name": "Foo", "price": 50.2},
"bar": {"name": "Bar", "description": "The Bar fighters", "price": 62, "tax": 20.2},
"baz": {
"name": "Baz",
"description": "There goes my baz",
"price": 50.2,
"tax": 10.5,
},
}
@app.get(
"/items/{item_id}/name",
response_model=Item,
response_model_include={"name", "description"},
)
async def read_item_name(item_id: str):
return items[item_id]
@app.get("/items/{item_id}/public", response_model=Item, response_model_exclude={"tax"})
async def read_item_public_data(item_id: str):
return items[item_id]
🤓 その他のバージョンとバリアント
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: float = 10.5
items = {
"foo": {"name": "Foo", "price": 50.2},
"bar": {"name": "Bar", "description": "The Bar fighters", "price": 62, "tax": 20.2},
"baz": {
"name": "Baz",
"description": "There goes my baz",
"price": 50.2,
"tax": 10.5,
},
}
@app.get(
"/items/{item_id}/name",
response_model=Item,
response_model_include={"name", "description"},
)
async def read_item_name(item_id: str):
return items[item_id]
@app.get("/items/{item_id}/public", response_model=Item, response_model_exclude={"tax"})
async def read_item_public_data(item_id: str):
return items[item_id]
ヒント
構文 {"name", "description"}
は、これら2つの値を持つ set
を作成します。
これは set(["name", "description"])
と同等です。
set
の代わりに list
を使用する¶
set
を使用するのを忘れて list
または tuple
を使用しても、FastAPI はそれを set
に変換し、正しく動作します。
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float = 10.5
items = {
"foo": {"name": "Foo", "price": 50.2},
"bar": {"name": "Bar", "description": "The Bar fighters", "price": 62, "tax": 20.2},
"baz": {
"name": "Baz",
"description": "There goes my baz",
"price": 50.2,
"tax": 10.5,
},
}
@app.get(
"/items/{item_id}/name",
response_model=Item,
response_model_include=["name", "description"],
)
async def read_item_name(item_id: str):
return items[item_id]
@app.get("/items/{item_id}/public", response_model=Item, response_model_exclude=["tax"])
async def read_item_public_data(item_id: str):
return items[item_id]
🤓 その他のバージョンとバリアント
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: float = 10.5
items = {
"foo": {"name": "Foo", "price": 50.2},
"bar": {"name": "Bar", "description": "The Bar fighters", "price": 62, "tax": 20.2},
"baz": {
"name": "Baz",
"description": "There goes my baz",
"price": 50.2,
"tax": 10.5,
},
}
@app.get(
"/items/{item_id}/name",
response_model=Item,
response_model_include=["name", "description"],
)
async def read_item_name(item_id: str):
return items[item_id]
@app.get("/items/{item_id}/public", response_model=Item, response_model_exclude=["tax"])
async def read_item_public_data(item_id: str):
return items[item_id]
まとめ¶
応答モデルを定義し、特にプライベートデータをフィルタリングするために、パス操作デコレータのパラメータ response_model
を使用してください。
明示的に設定された値のみを返すには、response_model_exclude_unset
を使用します。