Using pydantic setting management, how can I load env variables on nested setting objects on a main settings class? In the code below, the sub_field env variable field doesn't get loaded. field_one and field_two load fine. How can I load an environment file so the values are propagated down to the nested sub_settings object?
from typing import Optional
from pydantic import BaseSettings, Field
class SubSettings(BaseSettings):
sub_field: Optional[str] = Field(None, env='SUB_FIELD')
class Settings(BaseSettings):
field_one: Optional[str] = Field(None, env='FIELD_ONE')
field_two: Optional[int] = Field(None, env='FIELD_TWO')
sub_settings: SubSettings = SubSettings()
settings = Settings(_env_file='local.env')
There are some examples of nested loading of pydantic env variables in the docs.
If you're willing to adjust your variable names, one strategy is to use env_nested_delimiter to denote nested fields. This appears to be the way that pydantic expects nested settings to be loaded, so it should be preferred when possible.
So with a local.env like this:
FIELD_ONE=one
FIELD_TWO=2
SUB_SETTINGS__SUB_FIELD=value
You should be able to load the settings in this way
from typing import Optional
from pydantic import BaseModel, BaseSettings
class SubSettings(BaseModel):
# ^ Note that this inherits from BaseModel, not BaseSettings
sub_field: Optional[str]
class Settings(BaseSettings):
field_one: Optional[str]
field_two: Optional[int]
sub_settings: SubSettings
class Config:
env_nested_delimiter = '__'
If you don't want to use the env_nested_delimiter functionality, you could load both sets of settings from the same local.env file. Then pass the loaded SubSettings to Settings directly. This can be done by overriding the Settings class __init__ method
With this local.env
FIELD_ONE=one
FIELD_TWO=2
SUB_FIELD=value
use the following to load the settings
from typing import Optional
from pydantic import BaseModel, BaseSettings, Field
class SubSettings(BaseSettings):
sub_field: Optional[str]
class Settings(BaseSettings):
field_one: Optional[str]
field_two: Optional[int]
sub_settings: SubSettings
def __init__(self, *args, **kwargs):
kwargs['sub_settings'] = SubSettings(_env_file=kwargs['_env_file'])
super().__init__(*args, **kwargs)
settings = Settings(_env_file='local.env')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With