Pydantic models good practice in FastAPI

Viewed 1050

I am building a REST API with FastAPI and I really like the tool, especially the integration with Pydantic and OpenAPI.

For instance I can write the model taken by an endpoint as

class Model(BaseModel):
    field1: str = Field(default=...)
    field2: int = Field(default=...)
    field3: List[int] = Field(default=...)
    field4: float = Field(default=...)
    class Config:
        schema_extra = {
            "example": {
                'field1': 'example 1',
                'field2': 1,
                'field3': [1, 2],
                'field4': 1.3,
            }
        }

I find however that I have quite some repetitions in my code as for example if I want to create another class inheriting from Model that adds another field field5, I would need to re-write the Config class in order to define the new example.

Is there a good way of doing this? For example, is there any tool that allows you to define the fields with all the properties and example and then creating the class Model from a definition of what it requires to include?

Or any other pattern that is better suited for this is also welcome.

2 Answers

You could create a base schema extra and modify within each instantiation:

base_schema_extra = {
    "example": {
        'field1': 'example 1',
        'field2': 1,
        'field3': [1, 2],
        'field4': 1.3,
    }
}

class Model(BaseModel):
    field1: str = Field(default=...)
    field2: int = Field(default=...)
    field3: List[int] = Field(default=...)
    field4: float = Field(default=...)

    class Config:
        schema_extra = base_schema_extra


class Model2(BaseModel):
    field1: str = Field(default=...)
    field2: int = Field(default=...)
    field3: List[int] = Field(default=...)
    field4: float = Field(default=...)
    field5: bool = Field(default=...)

    class Config:
        schema_extra = dict(**base_schema_extra, **{'field5': True})

You can also inherit classes using the following:

class Model3(Model2):
    field6: bool = Field(default=...)

    class Config(Model.Config):
        schema_extra = dict(**Model.Config.schema_extra, **{'field6': False})

Declare another class that inherits from Base Model class. Add another field. The Config will remain the same but an extra example field.

class ChildModel(Model):
    field5: str = Field(default=...)
    class Config:
        schema_extra = {
            "example": {
                'field1': 'example 1',
                'field2': 1,
                'field3': [1, 2],
                'field4': 1.3,
                'field5': 'foo'
            }
        }

It will work, no issue

Related