Spaces:
Running
Running
File size: 4,798 Bytes
a152b95 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | # 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.
|