Skip to content
cccskills
FreePublished on GitHub

pydantic

Use when validating and serializing Python data with Pydantic v2 - models, field and model validators, constrained and special types, TypeAdapter, discriminated unions, BaseSettings, or FastAPI integration

The English summary is being prepared. Showing the original description.

Works withDiscord
See how to install

Files included (7)

  • SKILL.md9.1 KB
  • references/config-and-settings.md5.6 KB
  • references/django.md4.5 KB
  • references/fastapi.md2.3 KB
  • references/types-and-defaults.md6.2 KB
  • references/validation-patterns.md7.0 KB
  • references/validators.md7.6 KB

SKILL.md (original)

Review the instructions the agent will receive before you install.

Pydantic

Data validation using Python type annotations.

Overview

Pydantic provides data validation and settings management using Python type hints. Validates at runtime and generates JSON Schema.

Source: https://docs.pydantic.dev/ | https://github.com/pydantic/pydantic

Installation

pip install pydantic          # Core
pip install pydantic[email]   # Email validation
pip install pydantic orjson   # Best performance
pip install pydantic-settings # Settings management

Quick Start

from pydantic import BaseModel, Field

class User(BaseModel):
    id: int
    name: str
    email: str
    age: int | None = None

# Validation + coercion
user = User(id="1", name="John", email="john@example.com")  # id coerced to int

# From dict/JSON
user = User.model_validate({"id": 2, "name": "Jane", "email": "jane@example.com"})
user = User.model_validate_json('{"id": 3, "name": "Bob", "email": "bob@example.com"}')

# Serialization
data = user.model_dump()           # dict
json_str = user.model_dump_json()  # JSON string

Field Constraints

Compact examples—see validators.md for full reference.

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

class ConstrainedModel(BaseModel):
    # Strings
    name: str = Field(min_length=1, max_length=100)
    username: str = Field(pattern=r'^[a-zA-Z0-9_]+$')
    
    # Numbers
    age: int = Field(ge=0, le=150)
    price: float = Field(gt=0)
    
    # Collections
    tags: List[str] = Field(min_length=1)
    
    # Optional
    nickname: Optional[str] = Field(default=None, max_length=50)

Validators

See validators.md for comprehensive patterns.

from pydantic import BaseModel, field_validator, model_validator, Field
import re

class ValidatedModel(BaseModel):
    username: str
    password: str
    
    @field_validator('username')
    @classmethod
    def validate_username(cls, v: str) -> str:
        if len(v) < 3:
            raise ValueError('Username must be at least 3 characters')
        return v.strip().lower()
    
    @model_validator(mode='after')
    def validate_password_strength(self):
        if len(self.password) < 8:
            raise ValueError('Password too short')
        if not re.search(r'[A-Z]', self.password):
            raise ValueError('Password needs uppercase')
        return self

v1 → v2 Migration Checklist

Critical: v2 changes can silently break v1 code. Check each item.

v1v2Symptom
@validator@field_validatorImport error; validator deprecated
@validator(..., each_item=True)@field_validator with PlainSerializerList validation fails
@root_validator@model_validator(mode='before'/'after')root_validator removed; need mode
class Configmodel_config = ConfigDict(...)Config class ignored
.dict().model_dump()Method not found
.json().model_dump_json()Method not found
.parse_obj().model_validate()Method not found
.parse_raw().model_validate_json()Method not found
.schema().model_json_schema()Method not found
Field(..., regex=r'...')Field(pattern=r'...')regex removed
Field(..., min_length=...)Field(min_length=...)Works (unchanged)
copy(update={...})model_copy(update={...})copy is shallow; use model_copy
allow_population_by_field_namepopulate_by_nameConfig key renamed
orm_modefrom_attributesConfig key renamed
Optional[X] = None default behaviorDefaults no longer filled for NoneNone stays None, not replaced

Source: https://docs.pydantic.dev/latest/migration/

Serialization Performance

Measure before optimizing: use timeit or a profiler on model_dump() for deeply nested models.

from pydantic import BaseModel
from typing import Optional, List
import time

class NestedModel(BaseModel):
    data: dict
    items: List[str]

class DeepModel(BaseModel):
    level1: NestedModel
    level2: NestedModel
    level3: NestedModel

model = DeepModel(
    level1=NestedModel(data={}, items=[]),
    level2=NestedModel(data={}, items=[]),
    level3=NestedModel(data={}, items=[])
)

# Measure
start = time.perf_counter()
for _ in range(10000):
    model.model_dump()
print(f"Time: {time.perf_counter() - start:.3f}s")

Guidance:

  • model_dump() vs dict(model): model_dump() is O(1) per field; dict(model) triggers reflection O(fields) each call. Always use model_dump().
  • model_dump(mode="json"): Use when the consumer is JSON (serializes datetime, decimals, etc. to JSON-native types).
  • exclude_none=True: Omits fields with None value. Use when you want to hide nulls.
  • exclude_unset=True: Omits fields that were never explicitly set (even if they have defaults). Usually what you want for partial updates.
  • Deeply nested models: The hot spot. Profile first; consider selective include/exclude or flattening.

Django Integration

See django.md for detailed patterns.

from pydantic import BaseModel, ConfigDict
from myapp.models import User as UserModel

class UserPydantic(BaseModel):
    model_config = ConfigDict(from_attributes=True)
    
    id: int
    username: str
    email: str

# Accept ORM objects
user_orm = UserModel.objects.get(id=1)
user_py = UserPydantic.model_validate(user_orm)  # from_attributes=True enables this

# DjangoChoices for enum validation
from django.db import models

class Status(models.TextChoices):
    PENDING = "pending"
    ACTIVE = "active"

# Must be TextChoices, not plain str for enum validation
from pydantic import BaseModel

class Task(BaseModel):
    status: Status  # Works with TextChoices

Pitfalls:

  • Unsaved instances: Validating an unsaved Django model instance may fail if validators expect id or other DB-generated fields.
  • Lazy model fields: Use DjangoGetter wrapper for lazy evaluation of related fields (avoids N+1 queries).

When Not to Use a Strict Model

Not every case benefits from Pydantic's coercion:

  • Internal dataclasses: Where data is already validated at the boundary, coercion surprises hurt more than help. Use @dataclass or plain classes internally.
  • Boundary discipline: Validate external input ONCE at the boundary. Internal call sites should not re-validate—pass typed data directly.
  • Performance-critical paths: If validation is not needed (e.g., internal cache hits), skip Pydantic overhead.
# Good: Validate at boundary
def handle_request(raw_data: dict):
    user = User.model_validate(raw_data)  # Boundary
    process_user(user)  # Internal—no re-validation

def process_user(user: User):
    # Use user directly; trust the type
    send_email(user.email)

# Bad: Re-validating internally
def process_user_bad(raw_data: dict):
    user = User.model_validate(raw_data)
    # ...
    user_again = User.model_validate(user.model_dump())  # Unnecessary

Best Practices

  1. Use Field(default_factory=...) for mutable defaults

    class Model(BaseModel):
        tags: List[str] = Field(default_factory=list)  # Good
        # tags: List[str] = []  # Bad in v2
    
  2. Separate schemas for operations

    class UserBase(BaseModel):
        email: str
    
    class UserCreate(UserBase):
        username: str
        password: str
    
    class UserResponse(UserBase):
        id: int
        model_config = ConfigDict(from_attributes=True)
    
  3. Validate once at the boundary (see above)

Common Issues

Mutable Defaults

# v2 error: mutable default
class BadModel(BaseModel):
    items: list = []

# Fix: use default_factory
class GoodModel(BaseModel):
    items: list = Field(default_factory=list)

Performance

  • Use Pydantic v2 (parsing is 10-100x faster than v1)
  • Use orjson for serialization: model_config = ConfigDict(json_loads=orjson.loads, json_dumps=orjson.dumps)
  • Measure model_dump() on deeply nested models first

Deep Dives

Load these reference files on demand:

  • validators.md — Field/model validators, custom types, error handling, TypeAdapter, discriminated unions
  • types-and-defaults.md — Field aliases, naming conventions, constrained types, special types (email, URL, UUID, secrets, enums)
  • config-and-settings.md — Model configuration, strict mode, multi-environment settings, BaseSettings
  • django.md — Django ORM integration, DjangoGetter, TextChoices, unsaved instance pitfalls
  • fastapi.md — FastAPI integration with request/response models and nested validation

References

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

Use when building Python async HTTP services or clients with aiohttp - web server routing, middleware, WebSocket, SSE, streaming, client sessions, pytest-aiohttp testing, or troubleshooting SSL and timeout issues

The English summary is being prepared. Showing the original description.

CodeAtCode/oss-ai-skills24Updated Oct 9, 2026

Use when doing structural code search and rewriting - ast-grep linting, refactoring, multi-language patterns

The English summary is being prepared. Showing the original description.

CodeAtCode/oss-ai-skills24Updated Oct 9, 2026

Use when building GBA games with the BPCore Lua engine - entity, sprite and tilemap functions, SRAM save and load, link cable multiplayer protocol, camera and scrolling, or optimization patterns

The English summary is being prepared. Showing the original description.

CodeAtCode/oss-ai-skills24Updated Oct 9, 2026

celery

Free

Use when running background tasks with Celery - worker and broker configuration (Redis, RabbitMQ), task routing by name vs queue, chains/groups/chords, retry patterns (autoretry_for, retry_backoff), acks_late semantics, failure detection, and monitoring with Flower

The English summary is being prepared. Showing the original description.

CodeAtCode/oss-ai-skills24Updated Oct 9, 2026

django

Free

Use when building Django applications - security hardening, authentication and permissions, ORM optimization, PostgreSQL features, Django 6.0, migrations, testing, and ecosystem libraries

The English summary is being prepared. Showing the original description.

CodeAtCode/oss-ai-skills24Updated Oct 9, 2026

Use when customizing Django Admin - save_formset, get_search_results, formsets, queryset optimization, db_index, custom URLs

The English summary is being prepared. Showing the original description.

CodeAtCode/oss-ai-skills24Updated Oct 9, 2026

See all skills by CodeAtCode

Report a problem with this skill