Pydantic — Data Validation & Settings
Python's most widely used data validation library. Powered by Rust core in v2 (5–50x faster than v1). Type-hint-driven models with automatic parsing, validation, and serialization.
Installation
uv add pydantic
uv add pydantic-settings # env-based configuration
uv add email-validator # email string validation
When to Use What
| Tool |
Best for |
pydantic.BaseModel |
API request/response schemas, domain objects, config |
@dataclass (pydantic) |
Lighter models when you need dataclass compatibility |
TypeAdapter |
Validating non-model types (lists, dicts, primitives) |
BaseSettings |
App config from env vars, .env, secrets |
Section Map
| File |
Topics |
| 01 Models & Fields |
BaseModel, Field, types, constraints, nested models, aliases |
| 02 Validators & Serialization |
field_validator, model_validator, model_dump, field_serializer, computed_field |
| 03 Advanced Patterns |
Discriminated unions, generics, TypeAdapter, BaseSettings, JSON Schema |
| 04 Config & Performance |
Strict mode, ConfigDict, dataclasses, performance tips, FastAPI integration |
Cheat Sheet
Model Basics
from pydantic import BaseModel, Field
class User(BaseModel):
name: str
email: str = Field(max_length=255)
age: int = Field(ge=0, le=150)
role: str = "viewer"
Create & Validate
user = User(name="Alice", email="alice@example.com", age=30)
user = User.model_validate({"name": "Alice", "email": "alice@example.com", "age": 30})
user = User.model_validate_json('{"name":"Alice","email":"alice@example.com","age":30}')
Serialize
user.model_dump() # → dict
user.model_dump(exclude_unset=True) # only explicitly set fields
user.model_dump(by_alias=True) # use field aliases
user.model_dump_json() # → JSON string
user.model_dump(mode="json") # dict with JSON-safe types
Validators
from pydantic import field_validator, model_validator
class Order(BaseModel):
price: float
quantity: int
@field_validator("price")
@classmethod
def price_positive(cls, v: float) -> float:
if v <= 0:
raise ValueError("price must be positive")
return v
@model_validator(mode="after")
def check_total(self) -> "Order":
if self.price * self.quantity > 10_000:
raise ValueError("order total exceeds limit")
return self
Quick Rules
- Define models at boundaries — API input, DB rows, config files.
- Use
Field() constraints — ge, le, min_length, max_length, pattern.
- Prefer
model_validate() over manual __init__ for dict/JSON input.
- Use
field_validator for single-field rules, model_validator for cross-field.
- Call
model_dump(exclude_unset=True) for PATCH-style partial updates.
- Enable strict mode when you need exact types without coercion.
- Use
TypeAdapter to validate plain types (lists, unions) without a model.
See also