Settings Configuration¶
Complete guide to configuring application settings in core/config.py.
Overview¶
Settings are defined in core/config.py using Pydantic's BaseSettings. They automatically load from .env files and environment variables.
Settings Class Structure¶
Basic Settings¶
from pydantic import Field
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
"""
Application settings.
Loads from .env file automatically.
"""
database_url: str = Field(default="sqlite:///./app.db")
debug: bool = Field(default=False)
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
populate_by_name=True
)
Required Settings¶
Settings must implement SettingsProtocol, which requires:
database_url: str¶
Database connection string.
Type: str
Required: Yes (by protocol)
Default: "sqlite:///./app.db" (in scaffolded code)
Environment Variable: DATABASE_URL
Examples:
# SQLite
database_url: str = Field(default="sqlite:///./app.db")
# PostgreSQL
database_url: str = Field(default="postgresql://user:password@localhost:5432/mydb")
# MySQL
database_url: str = Field(default="mysql://user:password@localhost:3306/mydb")
debug: bool¶
Debug mode flag.
Type: bool
Required: Yes (by protocol)
Default: False
Environment Variable: DEBUG
Examples:
Adding Custom Settings¶
Basic Fields¶
Add any fields you need:
class Settings(BaseSettings):
database_url: str = Field(default="sqlite:///./app.db")
debug: bool = Field(default=False)
# Custom settings
secret_key: str = Field(default="change-me", alias="SECRET_KEY")
api_key: str = Field(default="", alias="API_KEY")
max_upload_size: int = Field(default=10485760, alias="MAX_UPLOAD_SIZE")
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
populate_by_name=True
)
Field Validation¶
Use Pydantic validators:
from pydantic import Field, field_validator
class Settings(BaseSettings):
database_url: str = Field(default="sqlite:///./app.db")
debug: bool = Field(default=False)
port: int = Field(default=8000, alias="PORT")
@field_validator('port')
@classmethod
def validate_port(cls, v: int) -> int:
if not (1 <= v <= 65535):
raise ValueError('Port must be between 1 and 65535')
return v
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
populate_by_name=True
)
Nested Settings¶
Use Pydantic models for nested configuration:
from pydantic import BaseModel, Field
class DatabaseConfig(BaseSettings):
host: str = "localhost"
port: int = 5432
name: str = "mydb"
user: str = "postgres"
password: str = ""
class Settings(BaseSettings):
database_url: str = Field(default="sqlite:///./app.db")
debug: bool = Field(default=False)
# Nested settings
database: DatabaseConfig = DatabaseConfig()
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
populate_by_name=True
)
Environment Variable Aliases¶
Use alias parameter to map to environment variables:
class Settings(BaseSettings):
database_url: str = Field(
default="sqlite:///./app.db",
alias="DATABASE_URL" # Maps to DATABASE_URL env var
)
debug: bool = Field(
default=False,
alias="DEBUG" # Maps to DEBUG env var
)
model_config = SettingsConfigDict(
env_file=".env",
populate_by_name=True # Allows both field name and alias
)
With populate_by_name=True, you can use either:
- Field name: database_url or DATABASE_URL in .env
- Alias: DATABASE_URL in environment variables
.env File¶
Location¶
The .env file should be in the project root (same directory as fastappkit.toml).
Format¶
# Database Configuration
DATABASE_URL=sqlite:///./myproject.db
# Development Settings
DEBUG=false
# Custom Settings
SECRET_KEY=your-secret-key-here
API_KEY=your-api-key
MAX_UPLOAD_SIZE=10485760
Variable Naming¶
- Use uppercase with underscores (e.g.,
DATABASE_URL) - Match the
aliasin Field definitions - No spaces around
=
Precedence¶
Settings are loaded in this order (highest to lowest priority):
- Environment variables (highest priority)
.envfile- Default values in
Field()(lowest priority)
Example:
# .env file
DATABASE_URL=sqlite:///./app.db
# Environment variable (overrides .env)
export DATABASE_URL=postgresql://localhost/mydb
Accessing Settings¶
Global Accessor (Django-like)¶
Use get_settings() function:
from fastappkit.conf import get_settings
settings = get_settings()
db_url = settings.database_url
is_debug = settings.debug
FastAPI Dependency Injection¶
Use as a dependency:
from fastappkit.conf import get_settings
from fastapi import Depends
from core.config import Settings
@app.get("/config")
def get_config(settings: Settings = Depends(get_settings)):
return {
"debug": settings.debug,
"database": settings.database_url
}
Settings Initialization¶
When Settings Are Loaded¶
Settings are initialized in core/app.py when the module is imported:
# core/app.py
from core.config import Settings
from fastappkit.core.kit import FastAppKit
# Initialize FastAppKit with project's Settings
settings = Settings() # Loads from .env automatically
kit = FastAppKit(settings=settings)
app = kit.create_app()
How FastAppKit Uses Settings¶
When FastAppKit is initialized, it calls set_settings() which makes settings globally available via get_settings().
CLI Commands and Settings¶
CLI commands use ensure_settings_loaded(project_root) which imports core.app, causing settings to be initialized automatically.
CRITICAL: Settings must be initialized in core/app.py before using FastAppKit. Without this, get_settings() will fail at runtime.
Complete Examples¶
Minimal Settings¶
from pydantic import Field
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
database_url: str = Field(default="sqlite:///./app.db")
debug: bool = Field(default=False)
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
populate_by_name=True
)
Extended Settings with Validation¶
from pydantic import Field, field_validator
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
database_url: str = Field(default="sqlite:///./app.db")
debug: bool = Field(default=False)
# Custom settings
secret_key: str = Field(default="change-me", alias="SECRET_KEY")
host: str = Field(default="127.0.0.1", alias="HOST")
port: int = Field(default=8000, alias="PORT")
redis_url: str = Field(default="redis://localhost:6379", alias="REDIS_URL")
@field_validator('port')
@classmethod
def validate_port(cls, v: int) -> int:
if not (1 <= v <= 65535):
raise ValueError('Port must be between 1 and 65535')
return v
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
populate_by_name=True,
extra="ignore", # Ignore extra fields from .env
)
Nested Settings¶
from pydantic import BaseModel, Field
from pydantic_settings import BaseSettings, SettingsConfigDict
class EmailConfig(BaseModel):
smtp_host: str = "smtp.gmail.com"
smtp_port: int = 587
smtp_user: str = ""
smtp_password: str = ""
from_email: str = "noreply@example.com"
class Settings(BaseSettings):
database_url: str = Field(default="sqlite:///./app.db")
debug: bool = Field(default=False)
# Nested settings
email: EmailConfig = EmailConfig()
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
populate_by_name=True
)
Settings Options Reference¶
| Setting | Type | Required | Default | Env Var | Description |
|---|---|---|---|---|---|
database_url |
str | Yes | sqlite:///./app.db |
DATABASE_URL |
Database connection string |
debug |
bool | Yes | False |
DEBUG |
Debug mode flag |
Common Custom Settings Examples¶
secret_key: Secret key for encryption/signinghost/port: Server host and portredis_url: Redis connection stringemail_settings: Nested email configurationlogging_level: Logging verbositycors_origins: CORS allowed originsapi_rate_limit: Rate limiting configuration
Common Issues¶
Settings Not Initialized¶
Error: Runtime errors when calling get_settings()
Solution: Ensure core/app.py initializes Settings and FastAppKit:
Missing .env File¶
Problem: Settings use defaults, may fail if no default for required field
Solution: Create .env file in project root with required settings
Wrong DATABASE_URL¶
Error: Database connection errors
Solution:
- Verify DATABASE_URL in .env file
- Check database is running and accessible
- Verify connection string format
External App Using Wrong DATABASE_URL¶
Problem: External app uses its own .env when developing independently, but should use core's when integrated
Solution:
- When developing independently: Use external app's .env
- When integrated: External app uses core project's DATABASE_URL (from core's .env)
Next Steps¶
- Project Configuration -
fastappkit.tomlreference - External App Manifest - External app configuration
- Creating Projects - Project setup guide