Vasily
Vasily

Reputation: 2514

Nested settings with pydantic-settings

Using pydantic-settings (v2.0.3), I want to manage settings for services service1 and service2, nesting them under the common settings object, so I can address them like settings.service1.secret1 or settings.service2.secret2. Currently, I have this code in my config.py:

from pydantic_settings import BaseSettings


class FirstServiceSettings(BaseSettings):
    secret1: str


class SecondServiceSettings(BaseSettings):
    secret2: str


class Settings(BaseSettings):
    service1: FirstServiceSettings
    service2: SecondServiceSettings

    class Config:
        env_file = ".env"


settings = Settings()

And this is my .env file:

secret1=secret1
secret2=secret2

However, I'm getting pydantic_core._pydantic_core.ValidationError: 4 validation errors for Settings.

The problem can be solved by adding service1__ and service2__ prefixes to keys in .env file and setting env_nested_delimiter = '__', but I wonder is there a way to make this without adding those prefixes in .env file.

Upvotes: 8

Views: 3876

Answers (1)

Michael H
Michael H

Reputation: 572

This problem can be solved using BaseModel and set extra='ignore' to BaseSettings:

from pydantic import BaseModel
from pydantic_settings import VERSION, BaseSettings, SettingsConfigDict

print(f'{VERSION = }')
# > VERSION = '2.0.3'


class BaseServiceSettings(BaseSettings):
    model_config = SettingsConfigDict(env_file='.env', extra='ignore')


class FirstServiceSettings(BaseServiceSettings):
    secret1: str


class SecondServiceSettings(BaseServiceSettings):
    secret2: str


class Settings2(BaseModel):
    service1: FirstServiceSettings = FirstServiceSettings()
    service2: SecondServiceSettings = SecondServiceSettings()


settings = Settings2()
print(settings.model_dump_json())
# > {"service1":{"secret1":"secret1"},"service2":{"secret2":"secret2"}}

Upvotes: 8

Related Questions