Explanation of the title:
Suppose we have the following setup of pydantic models:
class ParametersA(BaseModel):
param_a: str = Field(
default=...,
allow_mutation=False,
exclude=False,
description="some description.",
extra={
"additional_bool": False
}
)
param_b: bool = Field(
default=False,
allow_mutation=True,
exclude=False,
description="some description.",
extra={
"additional_bool": False
}
)
# many more parameters of all types with additional constaints (le, gt, max_items,...)
class ParametersB(BaseModel):
param_c: float = Field(
default=-22.0,
exclude=False,
allow_mutation=True,
description="some floaty description",
gt=-180.0,
le=0.0,
extra={
"additional_bool": False,
"unit": "degree"
}
)
param_d: List[str] = Field(
default=["auto"],
exclude=False,
allow_mutation=True,
min_items=1,
max_items=4,
unique_items=True,
description="Some listy description.",
extra={
"auto_mode_available": False
}
)
# many more parameters of all types with additional constaints (le, gt, max_items,...)
These two Models are fields in yet another BaseModel
:
class FullModelX(BaseModel):
parameters_A: ParametersA
parameters_B: ParametersB
The question is if it would be possible to create yet another model:
class FullModelY(BaseModel):
parameters_A: ParametersA
parameters_B: ParametersB
which can reuse the classes ParametersA
and ParametersB
but with different validation limits and different meta-data? So for example, in FullModelX
the default value for param_b
of ParametersA
might be False
, while in FullModelX
it should be True
. Same goes for any other FieldInfo
property such as exclude
, gt
, le
and so on..
So far my only solution is to duplicate ParametersA
and ParametersB
every time I need some other validation constraints.
So in most cases I think inheritance as suggested by the answer from user @Maxim would be the way to go.
In my particular case pretty much all of the model fields change on or the other FieldInfo
property, so inheritance would effectively mean rewriting the whole class.
I have found the following solution, which seems to fit my case a bit better. Going by my initial example of changing param_b
the code for FullModelY
would look something like this:
ParametersAVariant= create_model(
'ParametersAVariant',
__base__=ParametersA
)
ParametersAVariant.__fields__['param_b'].default=True
class FullModelY(BaseModel):
parameters_A: ParametersAVariant
parameters_B: ParametersB
Not sure if this make the code more readably than simple code duplication, but at least for the most part the initial model can be reused.