Skip to Content

URL-Based Database Configuration

Django-CFG uses URL-based database configuration for simplicity and security.

Why URL-Based Configuration?

Benefits:

  • ✅ Single string for all connection parameters
  • ✅ Easy to override with environment variables
  • ✅ Standard format across different databases
  • ✅ No hardcoded credentials in code
  • ✅ Compatible with 12-factor app methodology

URL Format

{engine}://{user}:{password}@{host}:{port}/{database}?{options}

Database Engines

SQLite

# File-based database url: str = "sqlite:///db/mydb.sqlite3" # Absolute path url: str = "sqlite:////absolute/path/to/db.sqlite3" # In-memory database url: str = "sqlite:///:memory:"

PostgreSQL

# Full URL with all parameters url: str = "postgresql://user:password@localhost:5432/dbname" # Default port (5432) url: str = "postgresql://user:password@localhost/dbname" # Short form (postgres instead of postgresql) url: str = "postgres://user:password@localhost/dbname" # With SSL url: str = "postgresql://user:pass@localhost/db?sslmode=require" # With connection timeout url: str = "postgresql://user:pass@localhost/db?connect_timeout=10" # Multiple options url: str = "postgresql://user:pass@localhost/db?sslmode=require&connect_timeout=10"

MySQL

# MySQL connection url: str = "mysql://user:password@localhost:3306/dbname" # With charset url: str = "mysql://user:pass@localhost/db?charset=utf8mb4"

Oracle

# Oracle connection url: str = "oracle://user:password@localhost:1521/dbname"

Configuration Examples

Development (SQLite)

# api/environment/loader.py from pydantic import Field from pydantic_settings import BaseSettings, SettingsConfigDict class DatabaseConfig(BaseSettings): url: str = Field(default="sqlite:///db/dev.sqlite3") model_config = SettingsConfigDict( env_prefix="DATABASE__", env_nested_delimiter="__", )
# .env (optional override) DATABASE__URL="sqlite:///db/dev.sqlite3"

Production (PostgreSQL)

# api/environment/loader.py from pydantic import Field from pydantic_settings import BaseSettings, SettingsConfigDict class DatabaseConfig(BaseSettings): url: str = Field(default="sqlite:///db/default.sqlite3") model_config = SettingsConfigDict( env_prefix="DATABASE__", env_nested_delimiter="__", )
# System ENV or Docker environment DATABASE__URL="postgresql://user:${DB_PASSWORD}@db.example.com:5432/production"

Environment Variable Override

# .env DATABASE__URL="postgresql://user:password@localhost:5432/mydb"
# api/environment/loader.py - automatically reads DATABASE__URL from pydantic import Field from pydantic_settings import BaseSettings, SettingsConfigDict class DatabaseConfig(BaseSettings): url: str = Field(default="sqlite:///db/default.sqlite3") # Fallback model_config = SettingsConfigDict( env_prefix="DATABASE__", env_nested_delimiter="__", )

Settings Integration

Django-CFG automatically converts URLs to Django’s DATABASES format:

# api/config.py from django_cfg import DjangoConfig, DatabaseConfig from .environment import env class MyDjangoConfig(DjangoConfig): databases = { "default": DatabaseConfig.from_url(url=env.database.url) } # Generate Django settings config = MyDjangoConfig()

Advanced Options

Connection Pooling

# PostgreSQL with connection pooling url: str = "postgresql://user:pass@localhost/db?pool_size=20&max_overflow=10"

SSL Configuration

# Require SSL url: str = "postgresql://user:pass@localhost/db?sslmode=require" # Verify SSL certificate url: str = "postgresql://user:pass@localhost/db?sslmode=verify-full&sslrootcert=/path/to/cert"

Timeouts

# Connection timeout url: str = "postgresql://user:pass@localhost/db?connect_timeout=10" # Statement timeout url: str = "postgresql://user:pass@localhost/db?options=-c statement_timeout=30000"

Character Encoding

# UTF-8 for MySQL url: str = "mysql://user:pass@localhost/db?charset=utf8mb4" # Client encoding for PostgreSQL url: str = "postgresql://user:pass@localhost/db?client_encoding=UTF8"

Security Best Practices

1. Never Hardcode Credentials

Bad:

url: str = "postgresql://admin:MyPassword123@localhost/db"

Good:

# System environment variable export DATABASE__URL="postgresql://admin:${DB_PASSWORD}@localhost/db" export DB_PASSWORD="MyPassword123"

Or in .env file (gitignored):

DATABASE__URL="postgresql://admin:MyPassword123@localhost/db"

2. Use Environment Variables in Production

# api/environment/loader.py from pydantic import Field from pydantic_settings import BaseSettings, SettingsConfigDict class DatabaseConfig(BaseSettings): url: str = Field(default="sqlite:///db/default.sqlite3") model_config = SettingsConfigDict( env_prefix="DATABASE__", env_nested_delimiter="__", )
# Production environment export DATABASE__URL="postgresql://prod_user:${DB_PASSWORD}@db.example.com/prod_db"

3. Different Credentials Per Environment

# Development (.env file) DATABASE__URL="postgresql://dev_user:dev_pass@localhost/dev_db"
# Production (system ENV or Docker) DATABASE__URL="postgresql://prod_user:${DB_PASSWORD}@db.example.com/prod_db"

Troubleshooting

Special Characters in Password

If password contains special characters, URL-encode them:

# Password: p@ssw0rd! # URL-encoded: p%40ssw0rd%21 url: str = "postgresql://user:p%40ssw0rd%21@localhost/db"

Or use Python’s urllib:

from urllib.parse import quote_plus password = "p@ssw0rd!" encoded_password = quote_plus(password) url = f"postgresql://user:{encoded_password}@localhost/db"

Connection Issues

# Test connection python manage.py check --database default # Verify URL parsing python manage.py shell >>> from django.conf import settings >>> print(settings.DATABASES['default'])

See Also