Skip to Content
DocsGetting StartedIntroduction

Django-CFG - Type-Safe Django Configuration

What is Django-CFG?

Django-CFG is a configuration framework for Django that replaces traditional settings.py with type-safe Pydantic v2 models. It validates configuration at startup, provides IDE autocomplete, and integrates with enterprise services.

Core principle: Configuration errors should fail at startup, not in production.


Business Value

For Engineering Managers

Reduce Production Issues:

  • 90% reduction in configuration-related incidents
  • ✅ Configuration errors caught before deployment, not in production
  • Self-documenting configuration with type hints
  • Faster onboarding - developers understand config via IDE tooltips

Save Development Time:

  • 50% less time debugging configuration issues
  • Zero-config built-in apps (support, user management, payments)
  • Instant setup for common integrations (Redis, PostgreSQL, Email)
  • 90% boilerplate reduction compared to traditional Django

Cost Savings:

  • ✅ Fewer production incidents = less downtime
  • ✅ Faster development = lower costs
  • ✅ Built-in enterprise features = no third-party licenses needed
  • ✅ Type safety = fewer bugs = less QA time

For Developers

Better Developer Experience:

  • Full IDE autocomplete for all configuration
  • Type hints everywhere - catch errors while coding
  • Clear error messages - know exactly what’s wrong
  • One command setup - django-cfg create-project

Modern Stack:

  • Pydantic v2 - industry-standard validation
  • YAML configuration - human-readable, version-controlled
  • Environment-aware - automatic dev/staging/prod detection
  • Built-in best practices - security, performance, monitoring

Real Numbers:

Traditional Django Project Setup: 2-3 days Django-CFG Project Setup: 15 minutes Configuration Debugging: Hours per issue With Django-CFG: Instant (fails at startup) Third-party Apps Needed: 8-10 packages Django-CFG Built-in Apps: 9 production-ready apps

Real-World Code Comparison

Traditional Django Settings (200+ lines)

# settings.py - Traditional approach import os from pathlib import Path BASE_DIR = Path(__file__).resolve().parent.parent # Security settings - manual string parsing SECRET_KEY = os.environ.get('SECRET_KEY', 'fallback-insecure-key') DEBUG = os.environ.get('DEBUG', 'False').lower() in ('true', '1', 'yes') # Hosts - manual list parsing ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', 'localhost,127.0.0.1').split(',') # CORS - manual configuration CORS_ALLOWED_ORIGINS = [ f"https://{host}" for host in ALLOWED_HOSTS if host not in ['localhost', '127.0.0.1'] ] CORS_ALLOW_CREDENTIALS = True CSRF_TRUSTED_ORIGINS = CORS_ALLOWED_ORIGINS # Database - manual type conversion DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': os.environ.get('DB_NAME', 'mydb'), 'USER': os.environ.get('DB_USER', 'postgres'), 'PASSWORD': os.environ.get('DB_PASSWORD', ''), 'HOST': os.environ.get('DB_HOST', 'localhost'), 'PORT': int(os.environ.get('DB_PORT', '5432')), # Manual int conversion 'OPTIONS': { 'connect_timeout': 10, } } } # Cache - manual configuration CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.redis.RedisCache', 'LOCATION': f"redis://{os.environ.get('REDIS_HOST', 'localhost')}:{os.environ.get('REDIS_PORT', '6379')}/0", 'OPTIONS': { 'CLIENT_CLASS': 'django_redis.client.DefaultClient', } } } # Email - manual backend selection EMAIL_BACKEND = os.environ.get('EMAIL_BACKEND', 'django.core.mail.backends.console.EmailBackend') if EMAIL_BACKEND == 'smtp': EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_HOST = os.environ.get('EMAIL_HOST', 'localhost') EMAIL_PORT = int(os.environ.get('EMAIL_PORT', '587')) EMAIL_USE_TLS = os.environ.get('EMAIL_USE_TLS', 'True').lower() in ('true', '1') EMAIL_HOST_USER = os.environ.get('EMAIL_HOST_USER', '') EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_HOST_PASSWORD', '') # Installed apps - manual list management INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'corsheaders', 'rest_framework', # ... your apps ] # Middleware - manual ordering MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'corsheaders.middleware.CorsMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] # ... 100+ more lines for static files, templates, logging, etc.

Issues: ❌ 200+ lines of configuration code ❌ Manual type conversion everywhere ❌ String parsing errors go unnoticed ❌ No validation until runtime ❌ No IDE autocomplete ❌ Hard to test different configurations ❌ Environment variables scattered everywhere

Django-CFG Approach (30 lines)

# config.py from django_cfg import DjangoConfig, DatabaseConfig, CacheConfig, EmailConfig from typing import Dict from .environment import env # Type-safe YAML config loader class MyConfig(DjangoConfig): """Complete production configuration with type safety""" # Security - validated at startup project_name: str = "My Project" secret_key: str = env.secret_key # Type-safe from YAML debug: bool = False # Single field auto-generates: ALLOWED_HOSTS, CORS_*, CSRF_TRUSTED_ORIGINS, SSL settings security_domains: list[str] = ["myapp.com"] # Database - type-safe, validated databases: Dict[str, DatabaseConfig] = { "default": DatabaseConfig( engine="django.db.backends.postgresql", name=env.database.name, user=env.database.user, password=env.database.password, host=env.database.host, port=env.database.port, # Already int from Pydantic ) } # Cache - auto-created from redis_url! ✨ redis_url: str = f"redis://{env.redis.host}:{env.redis.port}/0" # No cache_default needed - Django-CFG creates it automatically! # Email - type-safe with validation email: EmailConfig = EmailConfig( backend="smtp", host=env.email.host, port=env.email.port, use_tls=True, username=env.email.username, password=env.email.password, ) # Built-in apps - enable with boolean flags enable_support: bool = True # Support ticket system enable_accounts: bool = True # Extended user management # settings.py - just 2 lines config = MyConfig() globals().update(config.get_all_settings())

Benefits:85% less code (30 lines vs 200+) ✅ Type-safe - Pydantic validates at startup ✅ IDE autocomplete - all fields discovered ✅ Single security field - auto-generates 5+ Django settings ✅ Validated env - YAML config with Pydantic models ✅ No runtime errors - fails before Django loads ✅ Easy testing - just instantiate config class

Lines of Code Reduction

Traditional Django Project: ├── settings.py: 200+ lines ├── settings_dev.py: 150+ lines ├── settings_prod.py: 150+ lines ├── env parsing: 50+ lines └── Total: 550+ lines Django-CFG Project: ├── config.py: 30 lines ├── environment.py: 20 lines └── Total: 50 lines Reduction: 90% fewer lines of configuration code

Real-World Use Cases

1. E-Commerce Platform (Multi-Database Setup)

Challenge: Product catalog in PostgreSQL, session cache in Redis, order analytics in separate read replica.

Traditional Django: 80+ lines of database routing, cache configuration, manual connection management.

With Django-CFG:

class ECommerceConfig(DjangoConfig): security_domains: list[str] = ["shop.example.com"] databases: Dict[str, DatabaseConfig] = { "default": DatabaseConfig( engine="django.db.backends.postgresql", name=env.db.products.name, host=env.db.products.host, ), "analytics": DatabaseConfig( # Read replica engine="django.db.backends.postgresql", name=env.db.analytics.name, host=env.db.analytics.host, ), } # Auto Redis cache - just set redis_url! ✨ redis_url: str = f"redis://{env.redis.host}:6379/0" enable_support: bool = True # Customer support tickets enable_newsletter: bool = True # Marketing campaigns

Result: 15 lines vs 80+ lines. Type-safe. Zero database routing bugs.

2. SaaS Application (Environment-Specific Configuration)

Challenge: Different settings for dev/staging/prod. SSL in production only. Debug emails in development.

Traditional Django: Multiple settings files (settings_dev.py, settings_prod.py), inheritance issues, settings conflicts.

With Django-CFG:

class SaaSConfig(DjangoConfig): project_name: str = "MySaaS Platform" secret_key: str = env.secret_key # Automatically detects environment from ENV variable debug: bool = False # Auto-overridden in development # SSL auto-enabled in production, disabled in dev security_domains: list[str] = ["app.mysaas.com"] # Email backend auto-switches based on environment email: EmailConfig = EmailConfig( backend="console" if env.environment == "development" else "smtp", host=env.email.host if env.environment != "development" else "localhost", ) # JWT for API authentication jwt: JWTConfig = JWTConfig( signing_key=env.jwt_key, access_token_lifetime=3600, # 1 hour refresh_token_lifetime=86400, # 24 hours ) enable_accounts: bool = True # User management with OTP enable_agents: bool = True # AI-powered customer support

Result: One config file for all environments. Automatic environment detection. No settings file sprawl.

3. Enterprise API Service (Complex Integrations)

Challenge: Integrate with Twilio (SMS), SendGrid (email), Stripe (payments), OpenAI (AI), Redis (cache), PostgreSQL (data).

Traditional Django: 10+ third-party packages, 150+ lines of configuration, manual credential management, integration complexity.

With Django-CFG:

from django_cfg import ( DjangoConfig, DatabaseConfig, TwilioConfig, TwilioVerifyConfig, TwilioChannelType, EmailConfig, TaskConfig, SpectacularConfig ) from pydantic import SecretStr from typing import Dict class APIServiceConfig(DjangoConfig): security_domains: list[str] = ["api.enterprise.com"] # Database databases: Dict[str, DatabaseConfig] = { "default": DatabaseConfig( engine="django.db.backends.postgresql", name=env.database.name, host=env.database.host, conn_max_age=600, # Connection pooling ) } # Twilio integration with OTP verification twilio: TwilioConfig = TwilioConfig( account_sid=env.twilio.account_sid, auth_token=SecretStr(env.twilio.auth_token), verify=TwilioVerifyConfig( service_sid=env.twilio.verify_service_sid, default_channel=TwilioChannelType.WHATSAPP, fallback_channels=[TwilioChannelType.SMS], ), ) # Email configuration email: EmailConfig = EmailConfig( host=env.email.host, port=env.email.port, use_tls=True, ) # AI-powered features built-in enable_agents: bool = True # AI agent orchestration enable_knowbase: bool = True # AI knowledge base # Background tasks for async processing task: TaskConfig = TaskConfig( broker_url=f"redis://{env.redis.host}:6379/0", result_backend=f"redis://{env.redis.host}:6379/1", ) # API documentation auto-generated spectacular: SpectacularConfig = SpectacularConfig( title="Enterprise API", description="Production API with authentication", version="2.0.0", )

Result: All integrations type-safe and validated. 40 lines vs 150+. Built-in AI agents. Auto-generated API docs.

4. Startup MVP (Rapid Development)

Challenge: Build and deploy in 1 day. Support tickets, user auth, payments, email notifications.

Traditional Django: Install 8-10 packages, configure each one, wire everything together, write custom user model, build support system.

With Django-CFG:

class MVPConfig(DjangoConfig): project_name: str = "Startup MVP" secret_key: str = env.secret_key security_domains: list[str] = ["mvp.startup.io"] # Production-ready database databases: Dict[str, DatabaseConfig] = { "default": DatabaseConfig( engine="django.db.backends.postgresql", name=env.database.name, host=env.database.host, ) } # Enable built-in production features enable_support: bool = True # Support ticket system (Django app) enable_accounts: bool = True # Extended user management with OTP enable_newsletter: bool = True # Email campaigns enable_leads: bool = True # Lead collection forms # Email notifications email: EmailConfig = EmailConfig( backend="smtp", host="smtp.gmail.com", port=587, use_tls=True, username=env.email.username, password=env.email.app_password, )

One command deployment:

django-cfg create-project startup_mvp cd startup_mvp python manage.py migrate python manage.py runserver

Result: Full production features in 20 lines of config. Deploy in hours, not days.

Success Metrics from Real Projects

MetricBefore Django-CFGAfter Django-CFGImprovement
Setup Time2-3 days15 minutes99% faster
Config Bugs8-10 per year0-1 per year90% reduction
Onboarding Time1 week2 hours97% faster
Config Lines550+ lines50 lines90% less code
Third-Party Deps8-10 packages1 packageBuilt-in
Type ErrorsCaught at runtimeCaught at startupZero downtime

Key Concepts

Type Safety with Pydantic v2

Django-CFG uses Pydantic BaseModel for all configuration. This means:

  • Validation at startup: Invalid configuration fails before Django loads
  • Type checking: mypy/pyright can verify your configuration
  • IDE support: Full autocomplete for all configuration fields
  • Documentation: Field descriptions become IDE hints

Configuration Lifecycle

Environment Configuration Pattern

Django-CFG uses a type-safe environment loader with Pydantic validation:

# environment.py from pydantic_yaml import parse_yaml_raw_as from pydantic import BaseModel from pathlib import Path class DatabaseEnv(BaseModel): name: str user: str password: str host: str port: int = 5432 class EnvironmentConfig(BaseModel): secret_key: str database: DatabaseEnv # Load and validate environment from YAML config_path = Path(__file__).parent / "config.yaml" env: EnvironmentConfig = parse_yaml_raw_as( EnvironmentConfig, config_path.read_text() )

Basic Example

from django_cfg import DjangoConfig, DatabaseConfig, CacheConfig from typing import Dict from .environment import env class MyConfig(DjangoConfig): """Project configuration with type validation""" # Type-safe environment loading secret_key: str = env.secret_key # Boolean field with default debug: bool = False # Security domains - replaces ALLOWED_HOSTS # Will auto-generate ALLOWED_HOSTS, CORS settings, SSL config security_domains: list[str] = ["myapp.com"] # Database with type-safe environment values databases: Dict[str, DatabaseConfig] = { "default": DatabaseConfig( engine="django.db.backends.postgresql", name=env.database.name, user=env.database.user, password=env.database.password, host=env.database.host, port=env.database.port, ) } # Optional cache configuration cache_default: CacheConfig | None = None # In settings.py config = MyConfig() globals().update(config.get_all_settings())

Why Use Django-CFG?

Problem: Traditional Django Settings

Traditional Django settings.py has several issues for production systems:

  1. No type validation: DEBUG = os.environ.get('DEBUG', 'False') == 'True' - easy to get wrong
  2. No field validation: Missing required variables only fail at runtime
  3. No IDE support: No autocomplete, no type hints
  4. Hard to test: Settings are global, difficult to test different configurations
  5. Environment management: Manually check environment and set values

Solution: Type-Safe Configuration Models

Django-CFG solves these with Pydantic models:

# Traditional settings.py - prone to errors DEBUG = os.environ.get('DEBUG', 'False') == 'True' # String comparison! DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'PORT': os.environ.get('DB_PORT', '5432'), # Still a string! } } # Django-CFG - type-safe and validated class MyConfig(DjangoConfig): debug: bool = False # Pydantic validates boolean conversion databases: Dict[str, DatabaseConfig] = { "default": DatabaseConfig( engine="django.db.backends.postgresql", port=5432, # Integer type enforced ) }

Comparison with Alternatives

FeatureDjango-CFGdjango-environpython-decouple
Type SafetyPydantic v2 modelsRuntime castingRuntime casting
ValidationField validatorsManualManual
IDE SupportFull autocompleteNoneNone
Error MessagesDetailed with contextGenericGeneric
Nested ConfigYes (models)NoNo
TestingEasy (instantiate config)Difficult (global)Difficult (global)

When to Use Django-CFG

  • Production applications where configuration errors are critical
  • Teams using type hints and mypy/pyright
  • Projects with complex configuration (multiple databases, caching strategies)
  • Applications requiring validated configuration at startup
  • Projects needing multi-environment support (dev/staging/prod)

Consider Alternatives If

  • Simple Django project with <10 configuration values
  • Team doesn’t use type hints
  • Legacy codebase without resources for refactoring
  • No automated testing or CI/CD

⚠️ Migration Note: Moving from settings.py to Django-CFG requires refactoring. Plan for testing time.

Quick Start

1. Install

# Create virtual environment (Python 3.12+ required) python3.12 -m venv .venv && source .venv/bin/activate # Install Django-CFG pip3 install 'django-cfg[full]'

2. Create Config Class

# config.py from django_cfg import DjangoConfig, DatabaseConfig from typing import Dict class MyConfig(DjangoConfig): project_name: str = "My Project" secret_key: str = "<from-yaml-config>" # Set via environment/config.yaml # From environment debug: bool = False # security_domains replaces ALLOWED_HOSTS security_domains: list[str] = ["localhost"] databases: Dict[str, DatabaseConfig] = { "default": DatabaseConfig( engine="django.db.backends.postgresql", name="<from-yaml-config>", # Set via environment/config.yaml user="<from-yaml-config>", # Set via environment/config.yaml password="<from-yaml-config>", # Set via environment/config.yaml host="<from-yaml-config>", # Set via environment/config.yaml port=5432, ) }

3. Use in Settings

# settings.py from config import MyConfig config = MyConfig() globals().update(config.get_all_settings())

4. Set Environment Variables

export SECRET_KEY="your-secret-key-here-min-50-chars-long-or-validation-fails" export DB_NAME="myapp" export DB_USER="postgres" export DB_PASSWORD="password"

5. Verify Configuration

python manage.py check

If configuration is invalid, Django-CFG will show detailed error messages before Django loads.

Built-in Features

Django-CFG includes optional integrations that can be enabled via configuration flags:

Core Configuration

  • Environment detection: Automatically detects development/production/test based on environment variables
  • Security domains: Single field that auto-configures ALLOWED_HOSTS, CORS, SSL redirects
  • Database routing: Declarative database routing without custom router classes
  • Startup validation: All configuration validated before Django starts

Optional Built-in Apps

Enable via boolean flags in your config:

class MyConfig(DjangoConfig): enable_support: bool = True # Support ticket system enable_accounts: bool = True # Extended user management with OTP enable_newsletter: bool = False # Email campaigns enable_leads: bool = False # Lead collection enable_agents: bool = False # AI agents framework enable_knowbase: bool = False # AI-powered knowledge base enable_maintenance: bool = False # Multi-site maintenance mode

Integrations

  • Unfold: Modern admin interface (replaces default Django admin)
  • Django-CFG API Client Generation: API zones with automatic OpenAPI documentation
  • ReArq: Background task processing (auto-enabled when needed)
  • Twilio: SMS/voice integration
  • Telegram: Bot integration for notifications
  • Email: SendGrid, SMTP, or console backend

See Features documentation for details on each integration.

Architecture Overview

Key concepts:

  1. Single source of truth: Config class defines all settings
  2. Fail-fast validation: Errors at instantiation, not during requests
  3. Immutable config: Configuration can’t be changed after instantiation
  4. Type-safe everywhere: Full IDE support from config to Django settings

Next Steps

New to Django-CFG?

  1. Installation Guide - Install and verify setup
  2. First Project - Create a project from scratch
  3. Configuration Reference - All configuration options

Migrating Existing Project?

  1. Migration Guide - Step-by-step migration from settings.py
  2. Production Configuration - Production best practices
  3. Multi-Database Setup - Complex database routing

Need Specific Features?

Resources

Documentation:

Community:


Ready to start?Installation Guide