model_config vs class Config in Pydantic v2
Key takeaways:
- Replace the inner
class Configwithmodel_config = ConfigDict(...). orm_modebecomesfrom_attributes;allow_population_by_field_namebecomespopulate_by_name.json_encodersis replaced by field or model serializers.BaseSettingsusesSettingsConfigDict.- Confirm the configured behavior still applies after the change.
This is a focused slice of the Pydantic V2 Migration Guide.
The Problem This Solves
Configuration moved from an inner class to a typed dict, and several keys were renamed. A mechanical find-and-replace misses the renames, so a model can appear migrated while silently losing a setting like ORM compatibility. This guide maps the changes precisely.
Prerequisites
- Pydantic v2;
pydantic-settingsfor settings models.
Step-by-Step Implementation
1. The basic swap
# Pydantic v1
class User(BaseModel):
id: int
class Config:
orm_mode = True
allow_population_by_field_name = True
# Pydantic v2
from pydantic import BaseModel, ConfigDict
class User(BaseModel):
model_config = ConfigDict(
from_attributes=True, # was orm_mode
populate_by_name=True, # was allow_population_by_field_name
)
id: int
2. Replacing json_encoders
from datetime import datetime
from pydantic import BaseModel, field_serializer
class Event(BaseModel):
at: datetime
@field_serializer("at") # Replaces v1 Config.json_encoders.
def ser_at(self, value: datetime) -> str:
return value.isoformat()
3. Settings models
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
# SettingsConfigDict for BaseSettings; ConfigDict for plain models.
model_config = SettingsConfigDict(env_prefix="APP_", extra="forbid")
database_url: str
Edge Cases and Gotchas
- Silent key drops. A renamed key left under the old name is simply ignored; grep for
orm_mode,allow_population_by_field_name,json_encoders. extrabehavior. v2's defaults around extra fields differ; setextraexplicitly where it matters.- Mixed styles. Do not leave some models on
class Configand others onmodel_config; standardize.
Verification
def test_from_attributes_works():
class Row:
id = 7
assert User.model_validate(Row()).id == 7 # from_attributes in effect.
Related Reading
- Up to the topic: Pydantic V2 Migration Guide.
- Related guides: Migrate @validator to @field_validator and Managing Environment Variables with Pydantic Settings.