Both validators and extra columns have different ways of configuration in pydantic 2.*, I would like to know if I can still do a validation to take all the extra fields and put them in a single dictionary field
The expected behavior is:
class A(BaseModel):
name: str
extra_columns: Optional[Dict]
a = A(name="john", age=24, address="Brazil")
print(a)
>>> A(name="john", extra_columns={"age": 24, "address": "Brazil"})
My previous code:
@root_validator(pre=True)
def build_extra(cls, values: Dict[str, Any]) -> Dict[str, Any]:
all_required_field_names = {
field.alias for field in cls.__fields__.values() if field.alias != "extra_columns"
}
extra: Dict[str, Any] = {}
for field_name in list(values):
if field_name not in all_required_field_names:
extra[field_name] = values.pop(field_name)
values["extra_columns"] = extra
return values
Is possible to take the same behavior in pydantic 2.*?
This can be solved with model_validator:
from typing import Any
from pydantic import BaseModel, model_validator
class A(BaseModel):
name: str
extra_columns: dict | None = None
@model_validator(mode="before")
@classmethod
def set_extra_columns(cls, data: Any):
if isinstance(data, dict):
extra_fields = data.keys() - cls.model_fields.keys()
if extra_fields:
if "extra_columns" not in data:
data["extra_columns"] = {}
data["extra_columns"].update(
{field_name: data[field_name] for field_name in extra_fields}
)
return data
a = A(name="john", age=24, address="Brazil")
print(a)
# >>> name='john' extra_columns={'age': 24, 'address': 'Brazil'}