Spaces:
Running
Running
| # Configuration and Settings in FastAPI | |
| FastAPI leverages Pydantic's `BaseSettings` class to manage application configuration through environment variables, `.env` files, and secrets. This approach provides type-safe configuration with validation, default values, and automatic environment variable reading. | |
| ## Pydantic Settings | |
| Install the settings extension: | |
| ```bash | |
| pip install pydantic-settings | |
| ``` | |
| Define your settings as a Pydantic model: | |
| ```python | |
| from pydantic_settings import BaseSettings, SettingsConfigDict | |
| class Settings(BaseSettings): | |
| model_config = SettingsConfigDict( | |
| env_file=".env", | |
| env_file_encoding="utf-8", | |
| case_sensitive=False, | |
| env_prefix="", | |
| ) | |
| app_name: str = "My FastAPI App" | |
| admin_email: str = "admin@example.com" | |
| debug: bool = False | |
| database_url: str = "sqlite:///./app.db" | |
| redis_url: str = "redis://localhost:6379/0" | |
| allowed_hosts: list[str] = ["localhost", "127.0.0.1"] | |
| max_connections: int = 100 | |
| api_v1_prefix: str = "/api/v1" | |
| access_token_expire_minutes: int = 30 | |
| secret_key: str = "change-me-in-production" | |
| ``` | |
| Pydantic Settings reads values from these sources in the following priority order (highest priority first): | |
| 1. Constructor arguments passed directly to `Settings()` | |
| 2. Environment variables | |
| 3. Variables from the `.env` file | |
| 4. Default values defined in the model | |
| Setting `case_sensitive=False` (the default) means the environment variable `DATABASE_URL`, `database_url`, and `Database_Url` all map to the `database_url` field. | |
| ## Environment Variables and .env Files | |
| Create a `.env` file in the project root: | |
| ``` | |
| APP_NAME=Production API | |
| DEBUG=false | |
| DATABASE_URL=postgresql://user:pass@db-host:5432/mydb | |
| REDIS_URL=redis://redis-host:6379/0 | |
| MAX_CONNECTIONS=250 | |
| SECRET_KEY=a7f3b9c1d4e8f2a6b0c5d9e3f7a1b4c8 | |
| ACCESS_TOKEN_EXPIRE_MINUTES=60 | |
| ``` | |
| The `.env` file is parsed using the `python-dotenv` library (installed automatically with `pydantic-settings`). Multiple `.env` files can be specified as a tuple: | |
| ```python | |
| model_config = SettingsConfigDict( | |
| env_file=(".env", ".env.local"), | |
| ) | |
| ``` | |
| When multiple files are specified, later files take precedence over earlier ones. So `.env.local` overrides values from `.env`. | |
| ## Settings as a Dependency | |
| Use dependency injection to provide settings to route handlers: | |
| ```python | |
| from functools import lru_cache | |
| from fastapi import FastAPI, Depends | |
| app = FastAPI() | |
| @lru_cache | |
| def get_settings(): | |
| return Settings() | |
| @app.get("/info") | |
| async def info(settings: Settings = Depends(get_settings)): | |
| return { | |
| "app_name": settings.app_name, | |
| "admin_email": settings.admin_email, | |
| "debug": settings.debug, | |
| } | |
| ``` | |
| The `@lru_cache` decorator ensures the `Settings` object is created only once and reused for all subsequent requests. Without caching, Pydantic would read and parse the `.env` file on every request, adding approximately 1-3 milliseconds of overhead per call. The cache has no size limit by default (`maxsize=128` for `lru_cache`), but since `get_settings()` takes no arguments, it effectively stores just one instance. | |
| ## Nested Settings with Prefixes | |
| Organize related settings into nested models using `env_prefix`: | |
| ```python | |
| from pydantic_settings import BaseSettings, SettingsConfigDict | |
| from pydantic import BaseModel | |
| class DatabaseSettings(BaseSettings): | |
| model_config = SettingsConfigDict(env_prefix="DB_") | |
| host: str = "localhost" | |
| port: int = 5432 | |
| name: str = "mydb" | |
| user: str = "postgres" | |
| password: str = "" | |
| pool_min_size: int = 5 | |
| pool_max_size: int = 20 | |
| echo: bool = False | |
| class Settings(BaseSettings): | |
| model_config = SettingsConfigDict(env_file=".env") | |
| app_name: str = "My App" | |
| debug: bool = False | |
| db: DatabaseSettings = DatabaseSettings() | |
| ``` | |
| With `env_prefix="DB_"`, the environment variable `DB_HOST` maps to `DatabaseSettings.host`, `DB_PORT` maps to `port`, and so on. The default database pool sizes are 5 minimum and 20 maximum connections. | |
| ## Secrets Management | |
| For sensitive values, Pydantic Settings supports reading from secret files (commonly used with Docker Secrets and Kubernetes Secrets): | |
| ```python | |
| class Settings(BaseSettings): | |
| model_config = SettingsConfigDict( | |
| env_file=".env", | |
| secrets_dir="/run/secrets", | |
| ) | |
| database_password: str | |
| api_key: str | |
| jwt_secret: str | |
| ``` | |
| When `secrets_dir` is set, Pydantic looks for files named after each field (e.g., `/run/secrets/database_password`). The file contents become the field value. Secret files take precedence over `.env` values but are overridden by environment variables. | |
| The priority order with secrets becomes: constructor arguments > environment variables > secret files > `.env` file > default values. | |