Settings.ENVIRONMENT
doesn't work because the Settings
class isn't defined yet by the time it's referenced in the Config
definition. And self.ENVIRONMENT
doesn't work because self
here would refer to the Config
class, and not the Settings
class, which as mentioned, isn't fully defined yet, let alone has loaded the value for ENVIRONMENT
yet.
This design has a sort of circular dependency because the Settings
object needs to be initialized first (from direct __init__
or environment variables or env files) to set an ENVIRONMENT
value, ... but in order for Pydantic to initialize that class, it already needs to know which env_file
to read to get the field values, ... but the env_file
is determined by the ENVIRONMENT
value, ... and so on.
The simple alternative would be to separate them into 2 BaseSettings
classes instead:
class EnvConfig(BaseSettings):
ENVIRONMENT: str = "local"
class Settings(BaseSettings):
SECRET_KEY: str = "somekey"
Then create an instance of EnvConfig
first, then reference that instance in defining Settings
' Config.env_file
:
class EnvConfig(BaseSettings):
ENVIRONMENT: str = "local"
env_config = EnvConfig()
class Settings(BaseSettings):
SECRET_KEY: str = "somekey"
class Config:
env_file = ".env.development" if env_config.ENVIRONMENT == "development" else ".env.local"
$ cat .env.local
SECRET_KEY=localkey
$ ENVIRONMENT=local python test.py
SECRET_KEY='localkey'
$ cat .env.development
SECRET_KEY=developmentkey
$ ENVIRONMENT=development python test.py
SECRET_KEY='developmentkey'