← Zurück zum Blog
PydanticPython10. April 2026· 11 min Lesezeit

Pydantic in der Praxis: Datenvalidierung für Python

Inhalt
  1. Grundlagen: BaseModel
  2. Custom Validators
  3. Settings Management mit BaseSettings
  4. Pydantic mit Django
  5. Pydantic v2: Was ist neu?

Pydantic ist das meistgeladene Python-Package auf PyPI und das Fundament von FastAPI. Aber auch außerhalb von FastAPI ist es ein unglaublich nützliches Tool für saubere Datenvalidierung.

Grundlagen: BaseModel

from pydantic import BaseModel, EmailStr, Field
from datetime import datetime
from typing import Optional, List

class UserCreate(BaseModel):
    name: str = Field(min_length=2, max_length=100)
    email: EmailStr
    age: int = Field(ge=18, le=120)  # Zwischen 18 und 120
    tags: List[str] = []  # Default: leere Liste
    bio: Optional[str] = None

# Validierung
try:
    user = UserCreate(
        name="Yevhen",
        email="eugen@chubchyk.de",
        age=43
    )
    print(user.model_dump())
except ValidationError as e:
    print(e.errors())
# Verschachtelte Models
class Address(BaseModel):
    street: str
    city: str
    country: str = "DE"

class Company(BaseModel):
    name: str
    address: Address
    employees: List[UserCreate] = []

# JSON direkt parsen
json_str = '{"name": "Acme", "address": {"street": "Hauptstr. 1", "city": "Berlin"}}'
company = Company.model_validate_json(json_str)

Custom Validators

from pydantic import BaseModel, field_validator, model_validator

class OrderCreate(BaseModel):
    product_id: int
    quantity: int
    discount: float = 0.0
    price: float

    @field_validator("quantity")
    @classmethod
    def quantity_must_be_positive(cls, v):
        if v <= 0:
            raise ValueError("Menge muss größer 0 sein")
        return v

    @field_validator("discount")
    @classmethod
    def discount_range(cls, v):
        if not 0 <= v <= 1:
            raise ValueError("Rabatt muss zwischen 0 und 1 liegen")
        return v

    @model_validator(mode="after")
    def check_total_positive(self):
        total = self.price * self.quantity * (1 - self.discount)
        if total <= 0:
            raise ValueError("Gesamtpreis muss positiv sein")
        return self

Settings Management mit BaseSettings

from pydantic_settings import BaseSettings
from typing import Optional

class Settings(BaseSettings):
    # Liest aus Umgebungsvariablen (case-insensitive)
    database_url: str
    redis_url: str = "redis://localhost:6379/0"
    debug: bool = False
    secret_key: str
    allowed_hosts: list[str] = ["localhost"]
    api_rate_limit: int = 100

    class Config:
        env_file = ".env"
        env_file_encoding = "utf-8"

# Singleton Pattern
from functools import lru_cache

@lru_cache(maxsize=1)
def get_settings() -> Settings:
    return Settings()

settings = get_settings()

Pydantic mit Django

Pydantic und Django sind kein Gegensatz. Ich nutze Pydantic in Django für:

# 1. Validierung von externen API-Antworten
class GitHubUser(BaseModel):
    login: str
    id: int
    email: Optional[str] = None
    public_repos: int

import httpx

async def get_github_user(username: str) -> GitHubUser:
    async with httpx.AsyncClient() as client:
        r = await client.get(f"https://api.github.com/users/{username}")
    return GitHubUser.model_validate(r.json())

# 2. DTOs (Data Transfer Objects) zwischen Schichten
class ArticleDTO(BaseModel):
    id: int
    title: str
    author_name: str
    tags: List[str]

    @classmethod
    def from_model(cls, article) -> "ArticleDTO":
        return cls(
            id=article.id,
            title=article.title,
            author_name=article.author.get_full_name(),
            tags=list(article.tags.values_list("name", flat=True))
        )

Pydantic v2: Was ist neu?

Pydantic v2 (2023) ist in Rust geschrieben und 5-50x schneller als v1. Wichtige Änderungen:

Yevhen Chubchyk
Yevhen Chubchyk
Senior Python / Django Entwickler · Freelancer seit 2016 · 20+ Jahre IT-Erfahrung. Kunden: Siemens Healthineers, Engie, natureOffice u.a.