Pydantic Schema — データ検証とシリアライズ

この章ではPydantic Schemaを学び、ORMモデルとの責務分離を理解します。これはFastAPIの最も中核的な機能です。


なぜSchemaが必要なのか?

ORMモデル(models.py)はデータベース構造を定義しますが、APIのリクエスト/レスポンス検証には直接使用できません。

理由:ORMモデルにはデータベース専用のロジック(relationshipなど)が含まれており、すべてのフィールドをAPIに公開したくないためです。

Pydantic Schema純粋なデータクラスであり、APIの入力・出力検証とシリアライズを専門に担当します。

この三者(ORMモデル、Pydantic Schema、ルート)の関係:

客户端 → [Pydantic Schema 校验] → 路由函数 → [ORM 模型] → 数据库
客户端 ← [Pydantic Schema 序列化] ← 路由函数 ← [ORM 模型] ← 数据库

Pydantic Schema の基礎

Pydantic V2はFastAPIのデータエンジンであり、型ヒントを通じてデータ構造を定義します。

例

from pydantic import BaseModel, ConfigDict

class ItemCreate(BaseModel):
    """リクエスト作成用のSchema"""
    name: str
    price: float                       # 型を自動検証
    is_offer: bool = False             # デフォルト値付き(オプションフィールド)

class ItemResponse(BaseModel):
    """レスポンスSchema"""
    id: int
    name: str
    price: float

    # V2の書き方:ORMモードを有効にし、ORMオブジェクトから直接変換できるようにする
    model_config = ConfigDict(from_attributes=True)

ブログのSchemaを定義する

例

# ファイルパス:schemas.py
from pydantic import BaseModel, ConfigDict
from datetime import datetime
from typing import Optional

# ====== Category Schema ======
class CategoryBase(BaseModel):
    name: str
    slug: str

class CategoryResponse(CategoryBase):
    id: int
    model_config = ConfigDict(from_attributes=True)

# ====== Post Schema ======
class PostBase(BaseModel):
    title: str
    slug: str
    summary: Optional[str] = None      # Optional = Noneにできる
    content: str
    category_id: int

class PostCreate(PostBase):
    """記事作成時のリクエストボディSchema"""
    pass                               # PostBaseを直接継承し、フィールドは完全に一致

class PostUpdate(BaseModel):
    """記事の更新(すべてのフィールドはオプション)"""
    title: Optional[str] = None
    slug: Optional[str] = None
    summary: Optional[str] = None
    content: Optional[str] = None
    category_id: Optional[int] = None

class PostResponse(PostBase):
    """クライアントに返すレスポンスSchema"""
    id: int
    created_at: datetime
    updated_at: datetime
    category: CategoryResponse         # ネストされたSchema:カテゴリ情報を返す

    model_config = ConfigDict(from_attributes=True)
    # from_attributes=True は Pydantic に「このSchemaはORMオブジェクトから作成できる」ことを伝える

Pydantic V2では、model_config = ConfigDict(from_attributes=True)V1の を置き換えたものです。class Config: orm_mode = True。この設定により、SQLAlchemy ORMオブジェクトから直接Pydantic Schemaを構築できます:PostResponse.model_validate(post_orm_obj)。


ルートでSchemaを使用する

例

# ファイルパス:routers/posts.py(POSTルート作成の例)
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from database import get_db
from models import Post
from schemas import PostCreate, PostResponse

router = APIRouter(prefix="/posts", tags=["記事"])

# response_model=PostResponse を宣言すると:
# 1. FastAPIがORMオブジェクトを自動的にSchemaに変換(シリアライズ)
# 2. APIドキュメントにレスポンス構造が自動表示
@router.post("/", response_model=PostResponse, status_code=201)
def create_post(post_data: PostCreate, db: Session = Depends(get_db)):
    """
新規記事の作成
- post_data:リクエストボディ。FastAPIがPostCreate Schemaに従って自動検証
- db:Depends(get_db) によって注入されるデータベースセッション
    """

    post = Post(**post_data.model_dump())  # model_dump() でSchemaを辞書に変換する
    db.add(post)
    db.commit()
    db.refresh(post)                       # リフレッシュしてデータベースの自動採番IDを取得する
    return post                            # FastAPIがPostResponseで自動的にシリアライズする

response_modelFastAPIの最強の機能の1つです。宣言すると、FastAPIは:1. Schemaで宣言されていないORMオブジェクトのフィールドを自動的にフィルタリングします。2. datetimeなどの型を自動的にJSON文字列に変換します。3. 正確なOpenAPIドキュメントを生成します。


ORMモデル vs Pydantic Schema 対照

項目SQLAlchemy ORMモデルPydantic Schema
定義場所models.pyschemas.py
基底クラスBase (DeclarativeBase)BaseModel (Pydantic)
責務データベースのテーブル構造と関係を定義APIの入出力形式と検証ルールを定義
データベースとの関係データベーステーブルに直接マッピングデータベースには関知せず、API契約のみに関心を持つ
フィールド宣言Column(Integer, ...)Pythonの型ヒント:int, str
シリアライズJSONに直接変換できない組み込みの .model_dump() とJSONシリアライズ
変換方向ORM → Schema:model_validate(obj)Schema → ORM:Model(**schema.model_dump())

本章のまとめ

この章ではFastAPIの最も中核的なPydantic Schemaを習得しました:BaseModelによるリクエスト/レスポンスSchemaの定義、from_attributes=TrueによるORMモードの有効化、response_modelによるORMオブジェクトの自動シリアライズ、SchemaとORMモデルの責務分離の原則です。

これがFastAPIの型駆動アーキテクチャの真髄です——先にデータの形を定義すれば、ルートとドキュメントが自動生成されます。

その他の拡張