Pydantic Schema — Datenvalidierung und Serialisierung

In diesem Kapitel lernen Sie das Pydantic Schema kennen und verstehen seine Trennung der Zuständigkeiten von ORM-Modellen – dies ist FastAPIs zentralste Funktion.


Warum brauchen wir ein Schema?

ORM-Modelle (models.py) definieren die Datenbankstruktur, können aber nicht direkt für die Validierung von API-Anfragen/-Antworten verwendet werden.

Grund: ORM-Modelle enthalten datenbankspezifische Logik (wie Beziehungen), und Sie möchten nicht alle Felder über die API offenlegen.

Pydantic SchemaEs ist eine reine Datenklasse, die speziell für die Validierung und Serialisierung von API-Eingaben/-Ausgaben verantwortlich ist.

Die Beziehung zwischen diesen drei:

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

Pydantic Schema Grundlagen

Pydantic V2 ist die Daten-Engine von FastAPI und definiert Datenstrukturen durch Typ-Hinweise.

Beispiel

from pydantic import BaseModel, ConfigDict

class ItemCreate(BaseModel):
    """Schema zum Erstellen von Anfragen"""
    name: str
    price: float                       # Typ wird automatisch validiert
    is_offer: bool = False             # Mit Standardwerten (optionale Felder)

class ItemResponse(BaseModel):
    """Antwortschema"""
    id: int
    name: str
    price: float

    # V2-Ansatz: ORM-Modus aktivieren, direkte Konvertierung von ORM-Objekten ermöglichen.
    model_config = ConfigDict(from_attributes=True)

Definiere das Schema für den Blog

Beispiel

# Dateipfad: schemas.py
from pydantic import BaseModel, ConfigDict
from datetime import datetime
from typing import Optional

# ====== Kategorie-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 = kann None sein
    content: str
    category_id: int

class PostCreate(PostBase):
    """Request-Body-Schema zum Erstellen eines Artikels."""
    pass                               # Erbt direkt von PostBase, Felder sind identisch.

class PostUpdate(BaseModel):
    """Artikel aktualisieren (alle Felder optional)"""
    title: Optional[str] = None
    slug: Optional[str] = None
    summary: Optional[str] = None
    content: Optional[str] = None
    category_id: Optional[int] = None

class PostResponse(PostBase):
    """Antwort-Schema, das an den Client zurückgegeben wird."""
    id: int
    created_at: datetime
    updated_at: datetime
    category: CategoryResponse         # Verschachteltes Schema: Kategorieinformationen zurückgeben

    model_config = ConfigDict(from_attributes=True)
    from_attributes=True teilt Pydantic mit: Dieses Schema kann aus ORM-Objekten erstellt werden.

In Pydantic V2,model_config = ConfigDict(from_attributes=True)Ersetzt die in V1class Config: orm_mode = TrueDiese Konfiguration ermöglicht es dir, direkt ein Pydantic-Schema aus SQLAlchemy-ORM-Objekten zu erstellen:PostResponse.model_validate(post_orm_obj)。


Verwendung von Schema in Routen

Beispiel

# Dateipfad: routers/posts.py (Beispiel für das Erstellen einer POST-Route)
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=["Article"])

# Nach dem Deklarieren von response_model=PostResponse:
# 1. FastAPI konvertiert ORM-Objekte automatisch in Schema (Serialisierung)
# 2. API-Dokumentation zeigt die Antwortstruktur automatisch an
@router.post("/", response_model=PostResponse, status_code=201)
def create_post(post_data: PostCreate, db: Session = Depends(get_db)):
    """
Artikel erstellen
- post_data: Request-Body, FastAPI validiert automatisch gegen das PostCreate-Schema
db: Datenbank-Session, injiziert über Depends(get_db)
    """

    post = Post(**post_data.model_dump())  # model_dump() wandelt Schema in dict um
    db.add(post)
    db.commit()
    db.refresh(post)                       # Aktualisieren und Datenbank-Auto-Inkrement-ID abrufen
    return post                            # FastAPI serialisiert automatisch mit PostResponse.

response_modelEs ist eine der stärksten Funktionen von FastAPI. Sobald deklariert, wird FastAPI: 1. Felder aus ORM-Objekten, die nicht im Schema deklariert sind, automatisch herausfiltern; 2. Typen wie datetime automatisch in JSON-Strings umwandeln; 3. präzise OpenAPI-Dokumentation generieren.


Vergleich: ORM-Modell vs. Pydantic-Schema

AspektSQLAlchemy ORM-ModellPydantic-Schema
Definitionsortmodels.pyschemas.py
BasisklasseBase (DeclarativeBase)BaseModel (Pydantic)
VerantwortlichkeitenDatenbanktabellenstrukturen und Beziehungen definierenAPI-Eingabe-/Ausgabeformate und Validierungsregeln definieren.
Beziehung zur DatenbankWird direkt auf Datenbanktabellen abgebildetEs kümmert sich nicht um die Datenbank, sondern nur um den API-Vertrag.
FelddeklarationColumn(Integer, ...)Python-Typannotationen: int, str
SerialisierungKann nicht direkt in JSON konvertiert werdenEingebaute .model_dump()- und JSON-Serialisierung
KonvertierungsrichtungORM → Schema: model_validate(obj)Schema → ORM: Model(**schema.model_dump())

Kapitelzusammenfassung

In diesem Kapitel beherrschst du die zentralsten Pydantic-Schema-Konzepte von FastAPI: BaseModel zum Definieren von Request-/Response-Schemas, from_attributes=True zum Aktivieren des ORM-Modus, response_model zum automatischen Serialisieren von ORM-Objekten und das Prinzip der Trennung von Zuständigkeiten zwischen Schemas und ORM-Modellen.

Das ist die Essenz von FastAPIs typgetriebener Architektur – definiere zuerst die Datenform, und Routen sowie Dokumentation werden automatisch generiert.

Weitere Erweiterungen