Config decides how forgiving a model is, which matters as soon as models guard an API boundary.
Model-wide behavior is set with a class attribute model_config = ConfigDict(...) (it replaces v1's inner class Config). Settings are inherited by subclasses and can be overridden there.
The options you will reach for most:
extra: what to do with unknown keys."ignore"(default) drops them,"forbid"raisesextra_forbidden,"allow"keeps them, available viamodel_extra.frozen=True: instances are immutable and become hashable, so they can be dict keys or set members.validate_assignment=True:obj.field = valueis validated too; otherwise assignment is unchecked.strict=True: no type coercion at all;"42"is rejected for anint. You can also make single fields strict withField(strict=True)or callmodel_validate(data, strict=True)for one call.str_strip_whitespace=True,str_to_lower=True,str_max_length: global string handling.populate_by_name=True/validate_by_name=True: accept field names as well as aliases.from_attributes=True: validate from arbitrary objects such as ORM rows viamodel_validate(row).use_enum_values=True: store the enum's value instead of the member.
Strict mode is not all-or-nothing in JSON: when validating JSON, strict still accepts an ISO string for a datetime, since JSON has no date type.
Choose extra="forbid" for inbound API payloads where a typo like emial should fail loudly, and the default "ignore" for reading third-party data that may grow new fields.
Example
from pydantic import BaseModel, ConfigDict, ValidationError
class Point(BaseModel):
model_config = ConfigDict(frozen=True, extra="forbid")
x: int
y: int
p = Point(x=1, y="2")
print({p: "origin-ish"}[Point(x=1, y=2)]) # origin-ish (frozen -> hashable)
for bad in ({"x": 1, "y": 2, "z": 3}, {"x": "1", "y": 2}):
try:
Point.model_validate(bad, strict=True)
except ValidationError as e:
print(e.errors()[0]["type"]) # extra_forbidden, then int_type
class Account(BaseModel):
model_config = ConfigDict(validate_assignment=True)
balance: int
a = Account(balance=10)
try:
a.balance = "lots"
except ValidationError:
print("assignment rejected") # assignment rejectedRemember
- model_config = ConfigDict(...) replaces v1's class Config
- extra="forbid" catches typos in inbound payloads
- frozen=True makes instances immutable and hashable
- strict mode disables coercion per model, field or call
Watch out for
- Assuming attribute assignment is validated; it is not without validate_assignment=True.