pythonpydanticpydantic-settings

Use an environment variable with a different name in pydantic


I have a pydantic.BaseModel class where I'd like the variable node to have a default value based on an environment variable ENV_NODE_POOL.

Although my default environment variable works when I don't pass this variable, it seems to fail when I try to pass it. Would appreciate any help!

from pydantic import Field, BaseModel
from pydantic_settings import SettingsConfigDict

class WorkflowRun(BaseModel):
    id: str
    name: str
    node: str = Field(alias="env_node_pool")
    model_config = SettingsConfigDict(
        env_file=".env",
        env_file_encoding="utf-8",
        env_ignore_empty=True,
    )



WorkflowRun(**{
    "id": "1",
    "name": "test",
    "node": "test", # this fails
})

WorkflowRun(**{
    "id": "1",
    "name": "test",
    "env_node_pool": "test", # this succeeds
})

Error:

ValidationError: 1 validation error for WorkflowRun
env_node_pool
  Field required [type=missing, input_value={'id': '1', 'name': 'test', 'node': 'test'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.9/v/missing
Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...

Using pydantic.AliasChoices means that the default environment variable is not used:

from pydantic import Field, BaseModel, AliasChoices
from pydantic_settings import SettingsConfigDict

class WorkflowRun(BaseModel):
    id: str
    name: str
    node: str = Field(validation_alias=AliasChoices('node', 'ENV_NODE_POOL'))
    model_config = SettingsConfigDict(
        env_file=".env",
        env_file_encoding="utf-8",
        env_ignore_empty=True,
        populate_by_name=True,
    )
WorkflowRun(**{
    "id": "1",
    "name": "test",
})

returns this error

pydantic_core._pydantic_core.ValidationError: 1 validation error for WorkflowRun
node
  Field required [type=missing, input_value={'id': '1', 'name': 'test'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.9/v/missing

Solution

  • Using validation_alias with a BaseSettings class does the trick! It uses your environment variable's value as the default, whilst allowing you to override it when initializing an object.

    class WorkflowRun(BaseSettings):
        id: str
        name: str
        node: str = Field(validation_alias=AliasChoices('node', 'ENV_NODE_POOL'))
        model_config = SettingsConfigDict(
            env_file=".env",
            env_file_encoding="utf-8",
            extra="ignore",
            env_ignore_empty=True,
            populate_by_name=True,
        )
    

    Invocations:

    >>> WorkflowRun(**{
        "id": "1",
        "name": "test",
    })
    WorkflowRun(id='1', name='test', node='default-node')
    
    >>> WorkflowRun(**{
         "id": "1",
         "name": "test",
         "node": "new-pool"})
    WorkflowRun(id='1', name='test', node='new-pool')