Loading...
Loading...
This skill should be used when the user asks to "validate data with pydantic", "create a pydantic model", "use pydantic best practices", "write pydantic validators", or needs guidance on pydantic v2 patterns, serialization, configuration, or performance optimization.
npx skill4agent add the-perfect-developer/the-perfect-opencode pydanticBaseModelfrom pydantic import BaseModel, ConfigDict
class User(BaseModel):
model_config = ConfigDict(str_strip_whitespace=True, extra='forbid')
id: int
name: str
email: str | None = Nonemodel_config = ConfigDict(...)class Configextra='forbid'extra='ignore'extra='allow'int: int# From dict / Python objects
user = User.model_validate({'id': 1, 'name': 'Alice'})
# From JSON bytes/str — faster than model_validate(json.loads(...))
user = User.model_validate_json('{"id": 1, "name": "Alice"}')
# From ORM / arbitrary objects
class UserORM: ...
user = User.model_validate(orm_obj, from_attributes=True)model_validate_json()model_validate(json.loads(...))model_post_init__init__from typing import Any
from pydantic import BaseModel
class MyModel(BaseModel):
value: int
def model_post_init(self, context: Any) -> None:
# Runs after all field validators succeed
self._cache: dict = {}__init__model_post_initmodel_copyupdated = user.model_copy(update={'name': 'Bob'})
deep_copy = user.model_copy(deep=True)Annotatedfrom typing import Annotated
from pydantic import BaseModel, Field
PositivePrice = Annotated[float, Field(gt=0, description='Price in USD')]
ShortString = Annotated[str, Field(max_length=100)]
class Product(BaseModel):
name: ShortString
price: PositivePrice
quantity: Annotated[int, Field(ge=0)] = 0field: type = Field(...)from pydantic import BaseModel, Field
class Article(BaseModel):
title: str = Field(
min_length=1,
max_length=200,
title='Article Title',
description='The main headline',
examples=['Pydantic v2 released'],
)default_factoryfrom pydantic import BaseModel, Field
class Order(BaseModel):
# Correct — factory called per instance
items: list[str] = Field(default_factory=list)
tags: set[str] = Field(default_factory=set)[]{}default_factoryfrom pydantic import BaseModel, Field, ConfigDict
class Response(BaseModel):
model_config = ConfigDict(populate_by_name=True)
user_id: int = Field(alias='userId') # validation + serialization
created_at: str = Field(serialization_alias='createdAt') # serialization only| Mode | When to use |
|---|---|
| Post-type-coercion checks; input is already the correct type |
| Pre-coercion transformations; input may be raw/arbitrary |
| Full replacement of Pydantic's logic for a field |
| Need to intercept errors or run code both before and after |
afterfrom typing import Annotated
from pydantic import AfterValidator, BaseModel
def must_be_even(v: int) -> int:
if v % 2 != 0:
raise ValueError(f'{v} is not even')
return v
EvenInt = Annotated[int, AfterValidator(must_be_even)]
class Config(BaseModel):
batch_size: EvenInt
worker_count: EvenIntfield_validatorfrom pydantic import BaseModel, field_validator
class User(BaseModel):
first_name: str
last_name: str
@field_validator('first_name', 'last_name', mode='before')
@classmethod
def strip_whitespace(cls, v: str) -> str:
return v.strip()model_validatorfrom typing_extensions import Self
from pydantic import BaseModel, model_validator
class DateRange(BaseModel):
start: int
end: int
@model_validator(mode='after')
def check_range(self) -> Self:
if self.end <= self.start:
raise ValueError('end must be greater than start')
return selfValueErrorAssertionError-OPydanticCustomErrorfrom pydantic_core import PydanticCustomError
raise PydanticCustomError(
'invalid_format',
'Value {value!r} does not match the expected format',
{'value': v},
)from pydantic import BaseModel, ValidationInfo, field_validator
class Document(BaseModel):
text: str
@field_validator('text', mode='after')
@classmethod
def filter_words(cls, v: str, info: ValidationInfo) -> str:
if isinstance(info.context, dict):
banned = info.context.get('banned_words', set())
v = ' '.join(w for w in v.split() if w not in banned)
return v
doc = Document.model_validate(
{'text': 'hello world'},
context={'banned_words': {'hello'}},
)ValidationError.errors()from pydantic import BaseModel, ValidationError
class Item(BaseModel):
price: float
quantity: int
try:
Item(price='bad', quantity=-1)
except ValidationError as exc:
for error in exc.errors():
print(error['loc'], error['msg'], error['type'])ValidationError| Task | Recommended API |
|---|---|
| Validate from dict | |
| Validate from JSON | |
| Validate from ORM | |
| Dump to dict | |
| Dump to JSON | |
| Dump only set fields | |
| Copy with changes | |
| Skip validation | |
| Rebuild after forward refs | |
references/validators-and-fields.mdreferences/serialization-and-config.mdmodel_dumpConfigDictreferences/performance.mdTypeAdapterTypedDictFailFast