pythonpydantic

Is it possible to make different versions of the same pydantic basemodel?


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.


Solution

  • 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.