FastAPIでレスポンスSchemaを書いていると、
category_name: str = Field(alias="categoryName")
やConfigDict、response_modelが同時に登場します。
最初はどれも「レスポンスの形を設定するもの」に見えましたが、実際には役割が違います。
Field(alias=...)は名前を変える
Pythonではsnake_case、JSONではcamelCaseを使いたい場合があります。
from pydantic import BaseModel, Field
class HelpDetail(BaseModel):
category_name: str = Field(
alias="categoryName"
)
この場合、
Python
category_name
JSON
categoryName
のように名前を対応付けられます。
aliasは、Pydanticでvalidationとserializationの両方に利用できる別名です。
ConfigDictはモデル全体の動作を設定する
ConfigDictは、フィールドを必須にしたりNoneを許可したりするものではありません。
例えばaliasを設定したフィールドに、
HelpDetail(
category_name="アカウント"
)
のようにPython側の名前でも値を渡したい場合は、
from pydantic import ConfigDict
model_config = ConfigDict(
validate_by_name=True,
validate_by_alias=True,
)
と設定できます。
これにより、
HelpDetail(category_name="アカウント")
HelpDetail(categoryName="アカウント")
の両方を受け付けられます。
以前はpopulate_by_name=Trueがよく使われていましたが、Pydantic v2.11以降ではこの設定は推奨されておらず、validate_by_nameとvalidate_by_aliasを使う方法が案内されています。
from_attributes=Trueは別の役割
SQLAlchemyのORMオブジェクトからPydanticモデルを作る場合は、
model_config = ConfigDict(
from_attributes=True
)
を利用できます。
例えばORMオブジェクトの、
help.id
help.title
といった属性から値を読み取れるようになります。
つまり、
alias
→ フィールド名の対応
ConfigDict
→ Pydanticモデル全体の動作
from_attributes
→ オブジェクトの属性から値を取得
と分けて考えます。
response_modelはAPIのレスポンス契約
FastAPIでは、
@router.get(
"/help/{slug}",
response_model=HelpDetail,
)
async def read_help(...):
...
のようにresponse_modelを指定できます。
FastAPIはこのモデルを使って、
- レスポンスデータのvalidation
- JSONへのserialization
- OpenAPIへのSchema反映
- 定義されていないフィールドのfiltering
を行います。
つまり、Pydanticモデルが「データの形」を定義し、response_modelがそのモデルをAPIレスポンスの契約として使う役割を持っています。
まとめ
3つは次のように分けると理解しやすくなります。
Field(alias=...)
→ フィールド名を対応付ける
ConfigDict
→ Pydanticモデルの動作を設定する
response_model
→ APIが返すデータの形を指定する
それぞれの責務を分けて考えると、FastAPIのResponse Schemaがかなり読みやすくなります。