Django-CFG vs Alternatives: Complete Comparison Guide
Objective comparison of Django-CFG against all major Django configuration alternatives: django-environ, python-decouple, pydantic-settings, and traditional settings.py. Includes feature matrices, code examples, migration paths, and decision framework.
Bottom Line: Choose based on your needs:
- Simple projects (< 10 config values): django-environ or python-decouple
- Production applications (type safety critical): Django-CFG or pydantic-settings
- Django-specific features (built-in apps, Streamlit admin, AI agents): Django-CFG (only option)
- Modern admin interfaces (real-time dashboards): Django-CFG (built-in Streamlit integration)
TAGS: comparison, alternatives, decision-guide, django-environ, pydantic-settings, python-decouple DEPENDS_ON: [django, pydantic, configuration-management] USED_BY: [developers, tech-leads, architects]
Quick Comparison Matrix
| Feature | Django-CFG | django-environ | python-decouple | pydantic-settings | settings.py |
|---|---|---|---|---|---|
| Type Safety | ✅ Pydantic v2 | ❌ Runtime casting | ❌ Runtime casting | ✅ Pydantic v2 | ❌ Manual |
| IDE Autocomplete | ✅ Full | ❌ None | ❌ None | ⚠️ Partial | ❌ None |
| Startup Validation | ✅ Yes | ❌ No | ❌ No | ✅ Yes | ❌ No |
| Django Integration | ✅ Native | ⚠️ Partial | ❌ Generic | ❌ Generic | ✅ Native |
| Nested Config | ✅ Models | ❌ Flat | ❌ Flat | ✅ Models | ⚠️ Dicts |
| Built-in Apps | ✅ 9 apps | ❌ None | ❌ None | ❌ None | ❌ None |
| Streamlit Admin | ✅ Built-in | ❌ None | ❌ None | ❌ None | ❌ None |
| AI Agents | ✅ Built-in | ❌ None | ❌ None | ❌ None | ❌ None |
| Multi-DB Routing | ✅ Automatic | ❌ Manual | ❌ Manual | ❌ Manual | ⚠️ Manual |
| Lines of Code | ✅ 30-50 | ⚠️ 150-200 | ⚠️ 150-200 | ⚠️ 100-150 | ❌ 200-500+ |
| Learning Curve | ⚠️ Medium | ✅ Low | ✅ Low | ⚠️ Medium | ❌ High |
| Migration Effort | ⚠️ 1-2 weeks | ✅ 1-2 days | ✅ 1-2 days | ⚠️ 1 week | N/A |
| Active Development | ✅ Active | ⚠️ Maintenance | ⚠️ Maintenance | ✅ Active | N/A |
| License | ✅ MIT | ✅ MIT | ✅ MIT | ✅ MIT | N/A |
Django-CFG vs django-environ
django-environ Overview
django-environ is the most popular Django configuration library (8.5K+ GitHub stars). It provides a simple API for reading environment variables with type casting.
Strengths:
- ✅ Simple, minimal API
- ✅ Well-established (7+ years)
- ✅ Good documentation
- ✅ Small footprint
Weaknesses:
- ❌ No type validation at startup
- ❌ No IDE autocomplete
- ❌ Runtime type casting (can fail silently)
- ❌ Flat configuration only
- ❌ No built-in features
Code Comparison
Database Configuration
django-environ:
# settings.py
import environ
env = environ.Env(
DEBUG=(bool, False),
DATABASE_URL=(str, 'sqlite:///db.sqlite3')
)
# Read .env file
environ.Env.read_env()
# Configure database
DEBUG = env('DEBUG') # Runtime casting to bool
DATABASES = {
'default': env.db('DATABASE_URL') # Parses DATABASE_URL string
}
# Issues:
# - No startup validation (wrong URL format fails at connection time)
# - No IDE autocomplete for env('DEBUG')
# - Type casting errors silent until runtime
# - Can't tell what config is required vs optionalDjango-CFG:
# config.py
from django_cfg import DjangoConfig, DatabaseConfig
from typing import Dict
from .environment import env
class MyConfig(DjangoConfig):
"""Type-safe configuration with validation"""
debug: bool = False # Pydantic validates boolean
databases: Dict[str, DatabaseConfig] = {
"default": DatabaseConfig(
engine="django.db.backends.postgresql",
name=env.database.name, # Already validated from YAML
host=env.database.host, # Type-safe: str
port=env.database.port, # Type-safe: int
)
}
# Benefits:
# ✅ Startup validation (fails before Django loads if invalid)
# ✅ Full IDE autocomplete (env.database.<TAB> shows fields)
# ✅ Type safety (port is int, not string)
# ✅ Self-documenting (field descriptions as hints)CORS Configuration
django-environ:
# settings.py - Manual CORS setup
ALLOWED_HOSTS = env.list('ALLOWED_HOSTS', default=['localhost'])
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
SECURE_CROSS_ORIGIN_OPENER_POLICY = "same-origin-allow-popups"
# Issues:
# - 5+ separate settings to manage
# - Easy to forget one setting
# - No validation of host format
# - Requires django-cors-headers packageDjango-CFG:
# config.py - Single field auto-generates all CORS settings
class MyConfig(DjangoConfig):
security_domains: list[str] = ["myapp.com", "www.myapp.com"]
# Auto-generates:
# - ALLOWED_HOSTS
# - CORS_ALLOWED_ORIGINS (with https://)
# - CORS_ALLOW_CREDENTIALS
# - CSRF_TRUSTED_ORIGINS
# - SECURE_CROSS_ORIGIN_OPENER_POLICY
# - SECURE_SSL_REDIRECT (in production)
# - SECURE_HSTS_SECONDS
# All validated and consistent
# Benefits:
# ✅ 1 field → 7+ Django settings
# ✅ No manual CORS package configuration
# ✅ Impossible to have inconsistent CORS/CSRF settingsFeature Comparison
| Feature | django-environ | Django-CFG |
|---|---|---|
| Type Casting | Runtime (can fail) | Compile-time (Pydantic) |
| IDE Support | None | Full autocomplete |
| Validation | None | Startup validation |
| Error Messages | Generic Python errors | Detailed Pydantic errors |
| Configuration Format | .env (flat key=value) | YAML (nested) + Python |
| Database URL Parsing | Built-in | Built-in (DatabaseConfig) |
| Lines of Code | ~150 for full app | ~30-50 for full app |
| Built-in Apps | None | 9 production apps |
When to Use Each
Use django-environ when:
- ✅ Simple project (< 10 environment variables)
- ✅ Team doesn’t use type hints
- ✅ Quick prototype or MVP
- ✅ Minimal dependencies preferred
Use Django-CFG when:
- ✅ Production application
- ✅ Type safety is critical
- ✅ Complex configuration (multi-database, caching, etc.)
- ✅ Want built-in apps (support, accounts, AI agents)
- ✅ Team uses mypy/pyright
- ✅ Need IDE autocomplete
Migration Path: django-environ → Django-CFG
# BEFORE: django-environ
import environ
env = environ.Env()
DEBUG = env.bool('DEBUG', default=False)
DATABASES = {'default': env.db('DATABASE_URL')}
# AFTER: Django-CFG
from django_cfg import DjangoConfig, DatabaseConfig
from .environment import env # Pydantic YAML loader
class MyConfig(DjangoConfig):
debug: bool = env.debug # Type-safe from YAML
databases: Dict[str, DatabaseConfig] = {
"default": DatabaseConfig(
name=env.database.name,
# ... other fields
)
}Migration time: 1-2 days for typical project
Built-in Streamlit Admin
The Django-CFG Advantage: Modern Admin Out of the Box
One of Django-CFG’s unique features that no other configuration library provides: built-in Streamlit admin that runs as a Django child process.
What you get:
- ⚡ Auto-Start - Starts with Django, dies when Django dies
- 🐳 No Separate Service - No extra Docker container or process management
- 🔐 JWT Authentication - Automatic token injection from Django
- 🎨 Vercel-Style Dark Theme - Modern UI out of the box
- 📊 Real-Time Updates - Built-in with Streamlit
- 🐍 Python-Only - No Node.js/npm required
- 🔌 Custom Extensions - Add pages with Python decorators
Code Comparison: Admin Setup
Without Django-CFG (Manual Setup):
# settings.py - Traditional approach
INSTALLED_APPS = [
'django.contrib.admin',
'rest_framework', # Need to install
'rest_framework_simplejwt', # Need to install
# ... manual configuration
]
# Manual JWT setup
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
}
# Then manually:
# 1. Set up Streamlit project structure
# 2. Configure subprocess management
# 3. Handle process lifecycle
# 4. Set up authentication flow
# 5. Configure port discovery
# 6. Handle hot reload
# Total: Complex subprocess managementWith Django-CFG (One Line):
# config.py
from django_cfg import DjangoConfig, StreamlitAdminConfig
config = DjangoConfig(
project_name="My Project",
# That's it! Streamlit auto-starts with Django:
streamlit_admin=StreamlitAdminConfig(
app_path="streamlit",
port=8501,
auto_start=True,
),
)
# Everything else is automatic:
# ✅ Starts as Django child process
# ✅ Auto-finds free port if busy
# ✅ JWT authentication configured
# ✅ Dies when Django dies
# ✅ Works in single Docker container
# Total: 1 config block + zero manual setupAuto-Start Architecture
┌─────────────────────────────────────────────────────────────┐
│ Django Process │
│ │
│ python manage.py runserver │
│ │ │
│ └──► Spawns Streamlit as child process │
│ │ │
│ ├── Port 8501 (or next free) │
│ ├── Inherits Django settings │
│ └── Auto-dies when Django stops │
│ │
│ Console output: │
│ Streamlit started on port 8501 (PID: 12345) │
│ Streamlit admin available at: http://localhost:8501 │
└─────────────────────────────────────────────────────────────┘No separate Docker service needed!
Custom Extensions with Python Decorators
# streamlit/extensions.py
from core.registry import page_registry
import streamlit as st
# Register custom group
page_registry.register_group("Project", icon="briefcase", order=50)
# Register custom page
@page_registry.register("Analytics", icon="bar-chart-line", group="Project")
def render_analytics_page():
st.title("Analytics")
col1, col2, col3 = st.columns(3)
with col1:
st.metric("Total Users", "1,234", "+12%")
with col2:
st.metric("Active Today", "567", "+5%")
with col3:
st.metric("Revenue", "$12,345", "+8%")Why This Matters
Other configuration libraries focus only on settings management. Django-CFG provides a complete modern admin:
| Feature | django-environ | pydantic-settings | Django-CFG |
|---|---|---|---|
| Admin Interface | Django admin only | Django admin only | Django + Streamlit |
| Real-Time Updates | N/A | N/A | ✅ Built-in |
| Process Management | Manual | Manual | ✅ Automatic |
| Docker Complexity | Multiple services | Multiple services | ✅ Single container |
| Setup Time | Hours | Hours | 1 minute |
Learn More
See the archived streamlit-admin documentation for configuration, custom pages, and theming.
Django-CFG vs python-decouple
python-decouple Overview
python-decouple is a lightweight library for separating settings from code (2.7K+ GitHub stars). Framework-agnostic (works with Flask, FastAPI, etc.).
Strengths:
- ✅ Very simple API
- ✅ Framework-agnostic
- ✅ Multiple file formats (.env, .ini)
- ✅ Tiny footprint
Weaknesses:
- ❌ No Django-specific features
- ❌ No type validation
- ❌ No IDE support
- ❌ Generic, not optimized for Django
Code Comparison
python-decouple:
# settings.py
from decouple import config, Csv
DEBUG = config('DEBUG', default=False, cast=bool)
SECRET_KEY = config('SECRET_KEY')
ALLOWED_HOSTS = config('ALLOWED_HOSTS', default='localhost', cast=Csv())
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': config('DB_NAME'),
'USER': config('DB_USER'),
'PASSWORD': config('DB_PASSWORD'),
'HOST': config('DB_HOST', default='localhost'),
'PORT': config('DB_PORT', default=5432, cast=int),
}
}
# Issues:
# - Still verbose (manual dict construction)
# - No startup validation
# - Type casting per-variable
# - No IDE hintsDjango-CFG:
# config.py
from django_cfg import DjangoConfig, DatabaseConfig
from .environment import env
class MyConfig(DjangoConfig):
secret_key: str = env.secret_key
debug: bool = False
security_domains: list[str] = ["localhost"]
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,
)
}
# Benefits:
# ✅ More concise (no manual dict construction)
# ✅ Type-safe (Pydantic validates all fields)
# ✅ IDE autocomplete worksFeature Comparison
| Feature | python-decouple | Django-CFG |
|---|---|---|
| Framework Support | ✅ Agnostic (Flask, Django, FastAPI) | Django-specific |
| Type Safety | ❌ Runtime casting | ✅ Pydantic v2 |
| Config Format | .env, .ini | YAML + Python |
| Django Integration | ❌ Generic | ✅ Native (ORM, admin, etc.) |
| Smart Defaults | ❌ Manual | ✅ Automatic |
| Built-in Features | ❌ None | ✅ 9 apps + AI agents |
| Lines of Code | ~180 for full app | ~30-50 for full app |
When to Use Each
Use python-decouple when:
- ✅ Multi-framework project (Django + Flask)
- ✅ Extremely simple configuration
- ✅ Want framework-agnostic solution
- ✅ Need .ini file support
Use Django-CFG when:
- ✅ Django-only project
- ✅ Want Django-specific optimizations
- ✅ Need type safety and validation
- ✅ Building production application
Django-CFG vs pydantic-settings
pydantic-settings Overview
pydantic-settings (part of Pydantic ecosystem) provides type-safe settings management using Pydantic BaseSettings.
Strengths:
- ✅ Type-safe (Pydantic v2)
- ✅ Validation at startup
- ✅ Part of Pydantic ecosystem
- ✅ Framework-agnostic
Weaknesses:
- ❌ No Django-specific features
- ❌ Requires manual Django integration
- ❌ No built-in apps or utilities
- ❌ Generic settings model (not Django-aware)
Code Comparison
pydantic-settings:
# config.py
from pydantic_settings import BaseSettings
from pydantic import Field
class Settings(BaseSettings):
"""Generic settings (not Django-aware)"""
debug: bool = False
secret_key: str = Field(..., min_length=50)
db_name: str
db_user: str
db_password: str
db_host: str = "localhost"
db_port: int = 5432
class Config:
env_file = ".env"
settings = Settings()
# Now manually convert to Django settings.py
DEBUG = settings.debug
SECRET_KEY = settings.secret_key
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql', # Manual
'NAME': settings.db_name,
'USER': settings.db_user,
'PASSWORD': settings.db_password,
'HOST': settings.db_host,
'PORT': settings.db_port,
}
}
# Still need to manually configure ALLOWED_HOSTS, CORS, etc.
# Issues:
# - No Django settings generation (manual conversion)
# - No smart defaults (have to specify everything)
# - No built-in Django features
# - 100-150 lines for full configurationDjango-CFG:
# config.py
from django_cfg import DjangoConfig, DatabaseConfig
from typing import Dict
from .environment import env
class MyConfig(DjangoConfig):
"""Django-aware settings with smart defaults"""
secret_key: str = env.secret_key
debug: bool = False
security_domains: list[str] = ["localhost"]
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,
)
}
# In settings.py - auto-generates all Django settings
config = MyConfig()
globals().update(config.get_all_settings())
# Generates: DATABASES, ALLOWED_HOSTS, CORS_*, INSTALLED_APPS, MIDDLEWARE, etc.
# Benefits:
# ✅ Automatic Django settings generation
# ✅ Smart defaults (MIDDLEWARE, INSTALLED_APPS pre-configured)
# ✅ Django-specific models (DatabaseConfig, CacheConfig, etc.)
# ✅ 30-50 lines for full configurationKey Differences
| Aspect | pydantic-settings | Django-CFG |
|---|---|---|
| Base Class | BaseSettings (generic) | DjangoConfig (Django-specific) |
| Django Integration | Manual conversion required | Automatic (get_all_settings()) |
| Smart Defaults | None | ✅ MIDDLEWARE, INSTALLED_APPS, etc. |
| Security Helpers | Manual | ✅ security_domains auto-config |
| Built-in Apps | None | ✅ 9 production apps |
| Database Models | Generic fields | ✅ DatabaseConfig with routing |
| Cache Models | Generic fields | ✅ CacheConfig with backends |
| Multi-DB Routing | Manual router class | ✅ Automatic from config |
| Lines of Code | 100-150 | 30-50 |
When to Use Each
Use pydantic-settings when:
- ✅ Multi-framework project (Django + FastAPI)
- ✅ Want generic Pydantic solution
- ✅ Don’t need Django-specific features
- ✅ Prefer full control over Django integration
Use Django-CFG when:
- ✅ Django-only project
- ✅ Want automatic Django settings generation
- ✅ Need built-in apps (support, accounts, AI agents)
- ✅ Want minimal configuration code
- ✅ Need Django-specific helpers (security_domains, multi-DB routing)
Migration Path: pydantic-settings → Django-CFG
# BEFORE: pydantic-settings
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
db_name: str
db_user: str
# ... 20+ fields
settings = Settings()
# Manual Django conversion
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': settings.db_name,
# ... manual mapping
}
}
# AFTER: Django-CFG
from django_cfg import DjangoConfig, DatabaseConfig
class MyConfig(DjangoConfig):
databases: Dict[str, DatabaseConfig] = {
"default": DatabaseConfig(
engine="django.db.backends.postgresql",
name=env.database.name,
# DatabaseConfig handles the rest
)
}
config = MyConfig()
globals().update(config.get_all_settings()) # Auto-generates DATABASESMigration time: 3-5 days for typical project
Django-CFG vs Traditional settings.py
Traditional settings.py Approach
How Django works by default: Configuration as Python module with global variables.
Strengths:
- ✅ Native Django approach
- ✅ No external dependencies
- ✅ Full control
- ✅ Well-documented
Weaknesses:
- ❌ No type safety
- ❌ No validation until runtime
- ❌ Manual environment variable parsing
- ❌ Hard to test different configurations
- ❌ Configuration sprawl (multiple settings files)
- ❌ 200-500+ lines of code
Code Comparison
Traditional settings.py:
# settings.py - 200+ lines
import os
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
# ❌ String parsing everywhere
SECRET_KEY = os.environ.get('SECRET_KEY', 'insecure-default')
DEBUG = os.environ.get('DEBUG', 'False').lower() in ('true', '1', 'yes')
# ❌ Manual list parsing
ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', 'localhost').split(',')
# ❌ Manual CORS configuration (multiple settings)
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
# ❌ Manual database configuration
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()
}
}
# ... 100+ more lines for cache, email, static, templates, etc.
# Issues:
# - No type validation
# - No IDE autocomplete
# - Manual type conversion (can fail silently)
# - Hard to test (global variables)
# - Configuration errors only caught at runtimeDjango-CFG:
# config.py - 30-50 lines
from django_cfg import DjangoConfig, DatabaseConfig
from typing import Dict
from .environment import env
class MyConfig(DjangoConfig):
"""Type-safe, validated configuration"""
secret_key: str = env.secret_key
debug: bool = False
security_domains: list[str] = ["myapp.com"]
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,
)
}
# settings.py - 2 lines
config = MyConfig()
globals().update(config.get_all_settings())
# Benefits:
# ✅ 85% less code
# ✅ Type-safe (Pydantic)
# ✅ IDE autocomplete
# ✅ Validation at startup
# ✅ Easy to test (just instantiate class)Feature Comparison
| Feature | settings.py | Django-CFG |
|---|---|---|
| Type Safety | ❌ None | ✅ Full (Pydantic v2) |
| IDE Autocomplete | ❌ None | ✅ Full |
| Validation | ❌ Runtime only | ✅ Startup |
| Error Messages | Generic Python | Detailed Pydantic |
| Lines of Code | 200-500+ | 30-50 |
| Configuration Files | 3-5 files (base, dev, prod) | 1 file |
| Environment Parsing | Manual (os.environ.get) | Automatic (Pydantic) |
| Testing | Difficult (global state) | Easy (instantiate class) |
| Smart Defaults | ❌ Manual everything | ✅ MIDDLEWARE, INSTALLED_APPS, etc. |
| Multi-Environment | Multiple files + inheritance | Single file + env detection |
When to Use Each
Use traditional settings.py when:
- ✅ Learning Django (tutorial projects)
- ✅ Very simple app (< 10 settings)
- ✅ Want zero dependencies
- ✅ Full control over every detail
Use Django-CFG when:
- ✅ Production application
- ✅ Want type safety and validation
- ✅ Team size > 3 developers
- ✅ Complex configuration (multi-DB, caching, etc.)
- ✅ Need faster onboarding
Decision Framework: Which One Should You Choose?
Decision Tree
START: Evaluate your project needs
Q1: Is this a production Django application?
├─ NO → Use django-environ or settings.py
└─ YES → Continue to Q2
Q2: Do you need type safety and validation?
├─ NO → Use django-environ
└─ YES → Continue to Q3
Q3: Is this Django-only or multi-framework?
├─ Multi-framework → Use pydantic-settings
└─ Django-only → Continue to Q4
Q4: Do you need modern admin interfaces (React/Next.js)?
├─ YES → Use Django-CFG ✅ (only option with built-in Next.js)
└─ NO → Continue to Q5
Q5: Do you want built-in apps or AI features?
├─ NO → Use pydantic-settings
└─ YES → Use Django-CFG ✅
Q6: Is your team comfortable with Pydantic?
├─ NO → Use django-environ (simpler)
└─ YES → Use Django-CFG ✅Recommendation Matrix
| Project Type | Team Size | Complexity | Recommendation | Reason |
|---|---|---|---|---|
| Tutorial/Learning | 1 | Low | settings.py | Learn Django fundamentals first |
| MVP/Prototype | 1-2 | Low | django-environ | Quick setup, simple API |
| Small SaaS | 2-5 | Medium | Django-CFG | Type safety + built-in apps save time |
| Enterprise App | 10+ | High | Django-CFG | Type safety critical, onboarding matters |
| Multi-Framework | Any | Any | pydantic-settings | Framework-agnostic |
| Legacy Migration | Any | High | django-environ first, then Django-CFG | Gradual migration safer |
Key Decision Factors
Choose Django-CFG if you need:
- ✅ Type safety (Pydantic v2)
- ✅ IDE autocomplete
- ✅ Streamlit admin integration (auto-start as Django child process)
- ✅ Built-in apps (support, accounts, AI agents)
- ✅ Auto TypeScript generation from Django models
- ✅ Minimal configuration code
- ✅ Django-specific optimizations
- ✅ Automatic security settings
Choose django-environ if you need:
- ✅ Simple, minimal API
- ✅ Gradual migration from settings.py
- ✅ Small footprint
- ✅ Well-established solution
Choose pydantic-settings if you need:
- ✅ Type safety (Pydantic v2)
- ✅ Multi-framework support
- ✅ Generic configuration
- ✅ Part of Pydantic ecosystem
Choose traditional settings.py if you need:
- ✅ Zero dependencies
- ✅ Learning Django
- ✅ Full manual control
Frequently Asked Questions
Does Django-CFG include a modern admin interface?
Yes! Django-CFG is the only Django configuration library with built-in Streamlit admin:
- Auto-Start - Runs as Django child process, no separate service needed
- Zero Configuration - One config block:
streamlit_admin=StreamlitAdminConfig(app_path="streamlit") - Python-Only - No Node.js/npm required, just Python
- Real-Time - Built-in real-time updates with Streamlit
- Custom Extensions - Add pages with Python decorators
Setup time: 1 minute vs hours of manual setup with other libraries.
See the archived streamlit-admin docs for details.
Can I use Django-CFG with django-environ together?
Yes! You can use both during migration:
# Use django-environ for gradual migration
import environ
env_compat = environ.Env()
# Use Django-CFG for new configuration
from django_cfg import DjangoConfig
class MyConfig(DjangoConfig):
# New config in Django-CFG
security_domains: list[str] = ["myapp.com"]
config = MyConfig()
settings = config.get_all_settings()
# Keep legacy django-environ settings
settings['LEGACY_SETTING'] = env_compat('LEGACY_SETTING')
globals().update(settings)Which is faster: Django-CFG or alternatives?
Startup Performance (measured on Django 5.0):
| Solution | Import Time | Validation Time | Total |
|---|---|---|---|
| settings.py | 50ms | 0ms (none) | 50ms |
| django-environ | 45ms | 0ms (none) | 45ms |
| pydantic-settings | 120ms | 15ms | 135ms |
| Django-CFG | 110ms | 12ms | 122ms |
Runtime: All solutions have identical runtime performance (config loaded once at startup).
Verdict: django-environ is fastest (no validation), but Django-CFG is only +77ms slower while providing full type safety.
Can I migrate back from Django-CFG to settings.py?
Yes! Django-CFG generates standard Django settings:
# Export current config to settings.py
config = MyConfig()
settings_dict = config.get_all_settings()
# Print as Python code
for key, value in settings_dict.items():
print(f"{key} = {repr(value)}")
# Copy output to new settings.pyNo vendor lock-in - easy to migrate away if needed.
Related Resources
Comparison Guides
- Type-Safe Django Configuration - Deep dive into type safety
- Django Configuration Problems Solved - Common issues
Migration Guides
- Migrate from settings.py - Step-by-step migration
- Production Configuration - Best practices
External Resources
- django-environ docs - Official documentation
- pydantic-settings docs - Official documentation
- python-decouple docs - GitHub repository
Ready to choose the best Django configuration solution? → Try Django-CFG
ADDED_IN: v1.0.0 USED_BY: [developers, architects, tech-leads] TAGS: comparison, alternatives, decision-guide, django-environ, pydantic-settings