pydantic-dev
Pydantic Professional Development
Comprehensive guidance for building production-ready applications with Pydantic v2.12, the most widely used data validation library for Python.
Quick Reference
Installation: See references/install.md for setup instructions and optional dependencies
Core Philosophy: See references/why.md for Pydantic's design principles and when to use it
Migration from v1: See references/migration.md for upgrading from Pydantic v1.x
Core Concepts
Pydantic uses Python type hints to define data schemas and performs validation/coercion automatically. The fundamental building blocks are:
Models
Primary documentation: references/concepts/models.md
Define data structures by inheriting from BaseModel:
from pydantic import BaseModel, Field
class User(BaseModel):
id: int
name: str = Field(min_length=1, max_length=100)
email: str
age: int | None = None
Key concepts:
- Basic model usage and instantiation
- Data conversion and coercion
- Nested models and relationships
- Model methods:
model_validate(),model_dump(),model_dump_json() - Generic models and dynamic creation
- Immutability with
frozen=True
API reference: references/api/base_model/BaseModel.md - Complete BaseModel class documentation
Fields
Primary documentation: references/concepts/fields.md
Customize field behavior with constraints, defaults, and metadata:
from pydantic import BaseModel, Field
from typing import Annotated
class Product(BaseModel):
name: str = Field(description="Product name")
price: Annotated[float, Field(gt=0, description="Price in USD")]
quantity: int = Field(default=0, ge=0)
Key concepts:
- Field constraints (gt, ge, lt, le, min_length, max_length, pattern)
- Default values and factories
- Aliases and validation aliases
- Required vs optional fields
- Computed fields with
@computed_field
API reference: references/api/fields/ - Field, FieldInfo, and computed field APIs
Validators
Primary documentation: references/concepts/validators.md
Implement custom validation logic with field and model validators:
from pydantic import BaseModel, field_validator, model_validator
class Account(BaseModel):
username: str
password: str
password_confirm: str
@field_validator('username')
@classmethod
def username_alphanumeric(cls, v):
assert v.isalnum(), 'must be alphanumeric'
return v
@model_validator(mode='after')
def check_passwords_match(self):
if self.password != self.password_confirm:
raise ValueError('passwords do not match')
return self
Validator types:
- After validators: Run after Pydantic validation (type-safe, recommended)
- Before validators: Run before validation (for data preprocessing)
- Wrap validators: Full control over validation process
- Plain validators: Replace default validation entirely
API reference: references/api/functional_validators/ - All validator APIs and decorators
Types
Primary documentation: references/concepts/types.md
Pydantic supports all Python types plus specialized validation types:
Standard types: int, float, str, bool, list, dict, set, tuple, datetime, date, time, UUID, etc.
Pydantic types: See references/api/types/ for specialized types:
- Constrained types:
conint(),constr(),confloat(), etc. - Network types:
EmailStr,AnyUrl,IPvAnyAddress - Datetime types:
AwareDatetime,NaiveDatetime,FutureDate,PastDate - Special types:
Json,SecretStr,PaymentCardNumber,FilePath,DirectoryPath
Type documentation: references/concepts/types.md covers all supported types and patterns
Configuration
Primary documentation: references/concepts/config.md
Control model behavior with ConfigDict:
from pydantic import BaseModel, ConfigDict
class User(BaseModel):
model_config = ConfigDict(
str_strip_whitespace=True,
validate_assignment=True,
frozen=False,
extra='forbid'
)
Common settings:
extra: 'forbid' | 'allow' | 'ignore' - Handle extra fieldsvalidate_assignment: Validate on attribute assignmentfrozen: Make instances immutablestr_strip_whitespace: Strip whitespace from stringsfrom_attributes: Enable ORM mode for SQLAlchemy, etc.populate_by_name: Allow population by field name and alias
API reference: references/api/config/ConfigDict.md
Common Workflows
Validation Workflows
Parse untrusted data:
user = User.model_validate(data) # Raises ValidationError if invalid
Parse JSON:
user = User.model_validate_json(json_string)
Create without validation:
user = User.model_construct(**trusted_data) # Skip validation for performance
Handle validation errors: See references/errors/validation_errors.md
Serialization Workflows
Primary documentation: references/concepts/serialization.md
Export to dict:
user_dict = user.model_dump()
user_dict = user.model_dump(exclude={'password'})
user_dict = user.model_dump(by_alias=True)
Export to JSON:
json_str = user.model_dump_json()
json_str = user.model_dump_json(indent=2, exclude_none=True)
Custom serializers: See references/api/functional_serializers/
JSON Schema Generation
Primary documentation: references/concepts/json_schema.md
Generate schema:
schema = User.model_json_schema()
schema = User.model_json_schema(by_alias=True, mode='serialization')
Customize schema generation: See references/api/json_schema/GenerateJsonSchema.md
Settings Management
Primary documentation: references/concepts/pydantic_settings.md
For application configuration from environment variables:
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
database_url: str
api_key: str
debug: bool = False
model_config = ConfigDict(env_file='.env')
settings = Settings()
API reference: references/api/pydantic_settings/
Working with ORMs
Primary documentation: references/examples/orms.md
Pydantic integrates with SQLAlchemy, Django, and other ORMs:
from pydantic import BaseModel, ConfigDict
class UserModel(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: int
name: str
# Convert ORM instance to Pydantic model
user = UserModel.model_validate(sql_user)
Advanced Features
Dataclasses
Primary documentation: references/concepts/dataclasses.md
Use Pydantic with Python dataclasses:
from pydantic.dataclasses import dataclass
@dataclass
class User:
id: int
name: str
API reference: references/api/dataclasses/
Type Adapter
Primary documentation: references/concepts/type_adapter.md
Validate data against any type, not just models:
from pydantic import TypeAdapter
ListOfInts = TypeAdapter(list[int])
validated = ListOfInts.validate_python(['1', '2', '3'])
API reference: references/api/type_adapter/TypeAdapter.md
Unions and Discriminated Unions
Primary documentation: references/concepts/unions.md
Handle multiple possible types:
from typing import Literal, Union
from pydantic import BaseModel, Field
class Cat(BaseModel):
pet_type: Literal['cat']
meows: int
class Dog(BaseModel):
pet_type: Literal['dog']
barks: float
class Owner(BaseModel):
pet: Union[Cat, Dog] = Field(discriminator='pet_type')
Aliases
Primary documentation: references/concepts/alias.md
Map field names for validation and serialization:
from pydantic import BaseModel, Field
class User(BaseModel):
username: str = Field(alias='userName')
API reference: references/api/aliases/
Strict Mode
Primary documentation: references/concepts/strict_mode.md
Enforce strict type validation without coercion:
from pydantic import BaseModel, ConfigDict
class StrictModel(BaseModel):
model_config = ConfigDict(strict=True)
count: int # Won't accept '123', only 123
Performance Optimization
Primary documentation: references/concepts/performance.md
Guidelines for optimizing Pydantic performance in production
Error Handling
Validation Errors
Complete reference: references/errors/validation_errors.md
Understand and handle validation errors:
from pydantic import ValidationError
try:
user = User(**data)
except ValidationError as e:
print(e.errors()) # List of error dictionaries
print(e.json()) # JSON formatted errors
Error types reference: references/errors/errors.md - All validation error codes
Usage Errors
Reference: references/errors/usage_errors.md
Common mistakes and how to fix them
API Reference
Complete API documentation organized by module:
references/api/base_model/- BaseModel class and create_model()references/api/fields/- Field(), FieldInfo, computed fields, private attributesreferences/api/config/- ConfigDict and configuration optionsreferences/api/types/- All Pydantic types (constrained types, network types, etc.)references/api/functional_validators/- Validator decorators and classesreferences/api/functional_serializers/- Serializer decorators and classesreferences/api/json_schema/- JSON schema generation APIsreferences/api/dataclasses/- Pydantic dataclass supportreferences/api/type_adapter/- TypeAdapter for validating any typereferences/api/errors/- Error classesreferences/api/networks/- Network validation types (URLs, emails, IPs)references/api/aliases/- Alias configuration classesreferences/api/validate_call/- Function validation decoratorreferences/api/version/- Version information
Examples
Practical examples for common use cases:
references/examples/custom_validators.md- Building custom validatorsreferences/examples/orms.md- Integration with SQLAlchemy and Djangoreferences/examples/files.md- Validating file data (JSON, CSV, etc.)references/examples/requests.md- Validating API requests and responsesreferences/examples/queues.md- Using Pydantic with message queuesreferences/examples/dynamic_models.md- Creating models at runtime
Development Guidelines
Code Quality
Linting integration: references/integrations/linting.md - Configure ruff, mypy, and other linters
Best practices:
- Always type annotate fields explicitly
- Use
Field()for constraints and metadata - Prefer after validators over before validators
- Use discriminated unions for type safety
- Enable
validate_assignmentfor mutable models - Use
frozen=Truefor immutable data - Configure
extra='forbid'to catch typos
Production Readiness
Required considerations:
- Error handling: Always catch and handle
ValidationError - Performance: Use
model_construct()for trusted data - Security: Validate all external inputs
- Serialization: Test
model_dump()output matches expectations - Schema validation: Generate and validate JSON schemas for APIs
- Migration: Follow
references/migration.mdwhen upgrading
Testing
Validate your models:
def test_user_validation():
# Test valid data
user = User(id=1, name="Test", email="test@example.com")
assert user.id == 1
# Test invalid data
with pytest.raises(ValidationError):
User(id="invalid", name="Test")
Getting Help
- Overview:
references/index.md- Introduction to Pydantic - Help resources:
references/help_with_pydantic.md- Community support - Version policy:
references/version-policy.md- Versioning and deprecation - Contributing:
references/contributing.md- How to contribute to Pydantic
Version Information
This skill covers Pydantic v2.12.5 (December 2025). For migration from v1.x, see references/migration.md.