Reputation: 3201
I have this small example of nested object with pydantic.
from typing import Dict
from pydantic import BaseModel, Field, ValidationError
class UserType(BaseModel):
name: str = Field(min_length=1)
type: str = Field(min_length=1)
class AppConfig(BaseModel):
key1: int = Field(gt=0)
objects: Dict[str, UserType]
try:
data = {
"key1": 1,
"objects": {
"type1": {
"name": "Name 2",
},
"type2": {
"name": "Name 1"
}
}
}
c = AppConfig(**data)
print(c.model_dump_json())
except ValidationError as e:
print(e)
This obviously fail because type
is not set in UserType
model. My goal is to somehow set each UserType.type
using associated key from objects
dictionary before the actual validation. Something like:
type = key
inside data that is next is passed to UserType modelIs this possible somehow with pydantic
?
I know I could do all this before passing data to main model but I want to know if this is possible in pydantic
model.
I also tried using model_post_init()
method like this:
from typing import Dict
from pydantic import BaseModel, Field, ValidationError
class UserType(BaseModel):
name: str = Field(min_length=1)
type: str = Field(min_length=1)
class AppConfig(BaseModel):
key1: int = Field(gt=0)
objects: Dict[str, UserType]
def model_post_init(self, __context) -> None:
values = self.dict()
for obj_type, obj in values["objects"].items():
print(obj, obj_type)
obj["type"] = obj_type
try:
data = {
"key1": 1,
"objects": {
"type1": {
"name": "Name 2",
#"type": "t"
},
"type2": {
"name": "Name 1",
#"type": "t"
}
}
}
c = AppConfig(**data)
print(c.model_dump_json())
except ValidationError as e:
print(e)
But this method is executed after validation and validation failed earlier. Also tried to set some dummy type values in data payload and then override it in model_post_init()
but this did not work at all and model had only original dummy values for type.
Upvotes: 0
Views: 602
Reputation: 2353
You can update objects data before validation using field_validator
with mode=before
for objects
field:
from typing import Dict
from pydantic import BaseModel, Field, ValidationError, field_validator
class UserType(BaseModel):
name: str = Field(min_length=1)
type: str = Field(min_length=1)
class AppConfig(BaseModel):
key1: int = Field(gt=0)
objects: Dict[str, UserType]
@field_validator("objects", mode="before")
@classmethod
def validate_objects(cls, objects):
for obj_type, obj_dict in objects.items():
obj_dict.update({"type": obj_type})
return objects
try:
data = {
"key1": 1,
"objects": {
"type1": {
"name": "Name 2",
},
"type2": {
"name": "Name 1"
}
}
}
c = AppConfig.model_validate(data)
print(c.model_dump_json())
except ValidationError as e:
print(e)
Upvotes: 1