-
-
Notifications
You must be signed in to change notification settings - Fork 44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using multiple BaseSettings with different prefixes #179
Comments
Hello @alexdashkov , If I understand you correctly, you want to collect |
Hello @hramezani , Yes, exactly. |
The correct way to do it is defining BTW, here is the code if you want to use it: import os
from typing import Any
from pydantic_settings import BaseSettings, EnvSettingsSource, PydanticBaseSettingsSource, SettingsConfigDict
from pydantic.fields import FieldInfo
class CustomEnvSettingsSource(EnvSettingsSource):
def get_field_value(self, field: FieldInfo, field_name: str) -> tuple[Any, str, bool]:
if field_name in KubectlSecrets.model_fields:
env_name = (KubectlSecrets.model_config['env_prefix'] + field_name).lower()
return self.env_vars.get(env_name), field_name, False
else:
return super().get_field_value(field, field_name)
class KubectlSecrets(BaseSettings):
credentials: str
google_auth_key: str
model_config = SettingsConfigDict(env_prefix = "K8S_SECRET_")
@classmethod
def settings_customise_sources(
cls,
settings_cls: type[BaseSettings],
init_settings: PydanticBaseSettingsSource,
env_settings: PydanticBaseSettingsSource,
dotenv_settings: PydanticBaseSettingsSource,
file_secret_settings: PydanticBaseSettingsSource,
) -> tuple[PydanticBaseSettingsSource, ...]:
return init_settings, CustomEnvSettingsSource(settings_cls), dotenv_settings, file_secret_settings
class Settings(KubectlSecrets):
environment: str = "development"
redis_db: str = "0"
model_config = SettingsConfigDict(env_prefix = "")
os.environ["K8S_SECRET_CREDENTIALS"] = "dummy"
os.environ["K8S_SECRET_GOOGLE_AUTH_KEY"] = "dummy_key"
os.environ["ENVIRONMENT"] = "prod"
os.environ["REDIS_DB"] = "1"
print(Settings()) |
Thanks for your answer. Indeed it doesn't look like a very scalable code as I'll need to hardcode class name there so with a big chance it will require to add as much code as to put an alias everywhere. Could you also precise what kind of "the nested and complex model functionality" I can lose by using this loader? |
It was just an example, you can implement
settings models that have a field with the type of another Another simple way is to include import os
from pydantic_settings import BaseSettings, SettingsConfigDict
os.environ["K8S_SECRET_CREDENTIALS"] = "dummy"
os.environ["K8S_SECRET_GOOGLE_AUTH_KEY"] = "dummy_key"
os.environ["ENVIRONMENT"] = "prod"
os.environ["REDIS_DB"] = "1"
class KubectlSecrets(BaseSettings):
credentials: str
google_auth_key: str
model_config = SettingsConfigDict(env_prefix = "K8S_SECRET_")
class Settings(BaseSettings):
kubectl_secrets: KubectlSecrets = KubectlSecrets()
environment: str = "development"
redis_db: str = "0"
model_config = SettingsConfigDict(env_prefix = "")
print(Settings()) |
Yup, I was thinking about this implementation, but in my context is not acceptable because it initiates nested classes during the class declaration not the initialisation. In my case I'm passing multiple env files during the initialisation of the settings class. Anyway, I see a few possible ways to implement the functionality. Thanks for you help! |
Question
Hello,
I'm trying to migrate from the v1 to v2 and I'm looking for a way to implement multiple BaseSettings with different prefixes in the v2.
In the v1 I based my solution on this issue, and it worked well.
What I used to work with in v1:
I can workaround it by passing
Field(alias='base_prefix_1_...)
for each field for each model in the hierarchy but it adds a lot of copy / paste. Could you advise me how to get a similar to v1 solution in v2?Thanks for your help!
The text was updated successfully, but these errors were encountered: