Generator Pattern in Django-CFG
The Generator Pattern in Django-CFG is responsible for transforming configuration models into complete Django settings dictionaries. This pattern ensures type-safe, validated, and consistent Django settings generation.
Overview
Django-CFG uses specialized generator classes to convert Pydantic configuration models into Django-compatible settings. Each generator focuses on a specific aspect of Django configuration.
Key Benefits:
- Separation of Concerns: Each generator handles one category of settings
- Type Safety: Generators work with typed Pydantic models
- Validation: Settings validated before generation
- Extensibility: Easy to add custom generators
- Testing: Each generator independently testable
Architecture
DjangoConfig (Pydantic Model)
↓
ConfigService (Facade)
↓
SettingsOrchestrator (Coordinator)
↓
Specialized Generators (Category-specific)
↓
Complete Django Settings DictCore Components
SettingsGenerator (Facade)
The main entry point for settings generation.
Location: django_cfg.core.generation.generation
from django_cfg import DjangoConfig
from django_cfg.core.generation import SettingsGenerator
config = DjangoConfig(...)
settings = SettingsGenerator.generate(config)Responsibilities:
- Provide simple facade API
- Delegate to SettingsOrchestrator
- Validate generated settings
SettingsOrchestrator
Coordinates all specialized generators.
Location: django_cfg.core.generation.orchestrator
Responsibilities:
- Call generators in correct order
- Handle dependencies between settings
- Merge settings from all generators
- Validate final output
- Handle errors gracefully
Generation Order:
- Core Settings - BASE_DIR, DEBUG, SECRET_KEY
- Template Settings - TEMPLATES configuration
- Static Settings - STATIC_URL, STATICFILES
- Database Settings - DATABASES
- Cache Settings - CACHES
- Security Settings - ALLOWED_HOSTS, CORS, SSL
- Email Settings - EMAIL_BACKEND
- Logging Settings - LOGGING
- I18n Settings - LANGUAGE_CODE, TIME_ZONE
- Limits Settings - Upload limits
- Session Settings - SESSION_ENGINE
- Third-Party Settings - Unfold, Constance, etc.
- API Settings - DRF, Spectacular, JWT
- Tasks Settings - ReArq
Specialized Generators
Core Generators
CoreSettingsGenerator
Generates fundamental Django settings.
Location: django_cfg.core.generation.core_generators.settings
Generates:
BASE_DIR- Project root directorySECRET_KEY- Django secret keyDEBUG- Debug mode flagINSTALLED_APPS- Application list (via InstalledAppsBuilder)MIDDLEWARE- Middleware stack (via MiddlewareBuilder)ROOT_URLCONF- URL configurationWSGI_APPLICATION- WSGI app pathAUTH_USER_MODEL- Custom user model
Example Output:
{
"BASE_DIR": Path("/path/to/project"),
"SECRET_KEY": "your-secret-key",
"DEBUG": False,
"INSTALLED_APPS": [...],
"MIDDLEWARE": [...],
"ROOT_URLCONF": "myproject.urls",
"WSGI_APPLICATION": "myproject.wsgi.application",
}TemplateSettingsGenerator
Generates template configuration.
Location: django_cfg.core.generation.core_generators.templates
Generates:
TEMPLATES- Template backend configuration- Template directories
- Context processors
- Template options
Example Output:
{
"TEMPLATES": [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [BASE_DIR / "templates"],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
}
]
}StaticFilesGenerator
Generates static files configuration.
Location: django_cfg.core.generation.core_generators.static
Generates:
STATIC_URL- Static files URLSTATIC_ROOT- Static files collection directorySTATICFILES_DIRS- Additional static directoriesSTATICFILES_STORAGE- Storage backend (WhiteNoise)WHITENOISE_*- WhiteNoise configuration
Example Output:
{
"STATIC_URL": "/static/",
"STATIC_ROOT": BASE_DIR / "staticfiles",
"STATICFILES_STORAGE": "whitenoise.storage.CompressedManifestStaticFilesStorage",
"WHITENOISE_MANIFEST_STRICT": False,
}Data Generators
DatabaseSettingsGenerator
Generates database configuration from DatabaseConfig models.
Location: django_cfg.core.generation.data_generators.database
Generates:
DATABASES- Database connections dictionaryDATABASE_ROUTERS- Database routing (if configured)- Connection options
- SSL/TLS settings
Example Input:
databases = {
"default": DatabaseConfig(
engine="django.db.backends.postgresql",
name="mydb",
user="postgres",
password="secret",
host="localhost",
port=5432,
),
"analytics": DatabaseConfig(
engine="django.db.backends.postgresql",
name="analytics_db",
migrate_to="default", # Migrations go to default
),
}Example Output:
{
"DATABASES": {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": "mydb",
"USER": "postgres",
"PASSWORD": "secret",
"HOST": "localhost",
"PORT": 5432,
},
"analytics": {
"ENGINE": "django.db.backends.postgresql",
"NAME": "analytics_db",
"MIGRATE": False, # Handled by router
},
},
"DATABASE_ROUTERS": ["django_cfg.routing.DatabaseRouter"],
}CacheSettingsGenerator
Generates cache configuration from CacheConfig models.
Location: django_cfg.core.generation.data_generators.cache
Generates:
CACHES- Cache backends dictionary- Session cache configuration
- Cache key prefixes
- Cache options
Example Output:
{
"CACHES": {
"default": {
"BACKEND": "django.core.cache.backends.redis.RedisCache",
"LOCATION": "redis://localhost:6379/1",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
},
},
"sessions": {
"BACKEND": "django.core.cache.backends.redis.RedisCache",
"LOCATION": "redis://localhost:6379/2",
},
},
}Utility Generators
SecuritySettingsGenerator
Generates security-related settings.
Location: django_cfg.core.generation.utility_generators.security
Generates:
ALLOWED_HOSTS- (via SecurityBuilder)CORS_*- CORS configurationSECURE_*- SSL/TLS settingsCSRF_*- CSRF protectionSESSION_COOKIE_*- Cookie security
Example Output:
{
"ALLOWED_HOSTS": ["example.com", "www.example.com"],
"CORS_ALLOWED_ORIGINS": [
"https://example.com",
"https://www.example.com",
],
"CORS_ALLOW_CREDENTIALS": True,
"SECURE_SSL_REDIRECT": True,
"SECURE_HSTS_SECONDS": 31536000,
"SECURE_HSTS_INCLUDE_SUBDOMAINS": True,
"SESSION_COOKIE_SECURE": True,
"CSRF_COOKIE_SECURE": True,
}EmailSettingsGenerator
Generates email configuration.
Location: django_cfg.core.generation.utility_generators.email
Generates:
EMAIL_BACKEND- Email backend classEMAIL_HOST- SMTP serverEMAIL_PORT- SMTP portEMAIL_USE_TLS- TLS configurationEMAIL_HOST_USER- SMTP usernameEMAIL_HOST_PASSWORD- SMTP passwordDEFAULT_FROM_EMAIL- Default sender
LoggingSettingsGenerator
Generates logging configuration.
Location: django_cfg.core.generation.utility_generators.logging
Generates:
LOGGING- Complete logging dictionary- Formatters
- Handlers
- Loggers
- Log levels
I18nSettingsGenerator
Generates internationalization settings.
Location: django_cfg.core.generation.utility_generators.i18n
Generates:
LANGUAGE_CODE- Default languageTIME_ZONE- Default timezoneUSE_I18N- Enable internationalizationUSE_L10N- Enable localizationUSE_TZ- Enable timezone support
LimitsSettingsGenerator
Generates application limit settings.
Location: django_cfg.core.generation.utility_generators.limits
Generates:
DATA_UPLOAD_MAX_MEMORY_SIZE- Max upload sizeFILE_UPLOAD_MAX_MEMORY_SIZE- Max file sizeDATA_UPLOAD_MAX_NUMBER_FIELDS- Max form fieldsFILE_UPLOAD_HANDLERS- Upload handlers
Integration Generators
SessionSettingsGenerator
Generates session configuration.
Location: django_cfg.core.generation.integration_generators.sessions
Generates:
SESSION_ENGINE- Session backendSESSION_CACHE_ALIAS- Cache for sessionsSESSION_COOKIE_*- Cookie settings
ThirdPartyIntegrationsGenerator
Generates third-party package settings.
Location: django_cfg.core.generation.integration_generators.third_party
Generates:
CONSTANCE_*- django-constance settingsUNFOLD- Unfold admin configurationIMPORT_EXPORT_*- django-import-export settings
APIFrameworksGenerator
Generates API framework settings.
Location: django_cfg.core.generation.integration_generators.api
Generates:
REST_FRAMEWORK- DRF configurationSPECTACULAR_SETTINGS- drf-spectacular configurationSIMPLE_JWT- JWT authentication settings
TasksSettingsGenerator
Generates background task settings.
Location: django_cfg.core.generation.integration_generators.tasks
Generates:
REARQ_BROKER- Task broker configurationREARQ_RESULT_BACKEND- Result storageREARQ_TASKS_DATABASE- Task database
Creating Custom Generators
You can create custom generators for your own settings:
from typing import Dict, Any, TYPE_CHECKING
if TYPE_CHECKING:
from django_cfg.core.base.config_model import DjangoConfig
class CustomSettingsGenerator:
"""Generate custom application settings."""
def __init__(self, config: "DjangoConfig"):
self.config = config
def generate(self) -> Dict[str, Any]:
"""
Generate settings from configuration.
Returns:
Dictionary with Django settings
"""
settings = {}
# Your custom logic
if hasattr(self.config, 'custom_feature'):
settings["CUSTOM_FEATURE_ENABLED"] = self.config.custom_feature
return settingsIntegration Example
Complete flow from config to settings:
from django_cfg import DjangoConfig
from django_cfg.models import DatabaseConfig, CacheConfig
# 1. Define configuration
class MyProjectConfig(DjangoConfig):
project_name = "My Project"
secret_key = "your-secret-key"
databases = {
"default": DatabaseConfig(
engine="django.db.backends.postgresql",
name="mydb",
)
}
cache_default = CacheConfig(
backend="django.core.cache.backends.redis.RedisCache",
location="redis://localhost:6379/1",
)
# 2. Instantiate configuration
config = MyProjectConfig()
# 3. Generate settings (happens automatically in get_all_settings)
settings = config.get_all_settings()
# Behind the scenes:
# - SettingsGenerator.generate(config)
# - SettingsOrchestrator(config).generate()
# - Each specialized generator runs
# - Settings merged and returnedTesting Generators
Generators are designed to be testable:
import pytest
from django_cfg import DjangoConfig
from django_cfg.core.generation.core_generators.settings import CoreSettingsGenerator
def test_core_settings_generator():
config = DjangoConfig(
project_name="Test Project",
secret_key="x" * 50,
databases={"default": DatabaseConfig(...)},
)
generator = CoreSettingsGenerator(config)
settings = generator.generate()
assert "SECRET_KEY" in settings
assert "DEBUG" in settings
assert "INSTALLED_APPS" in settings
assert settings["DEBUG"] == config.debug
def test_database_settings_generator():
config = DjangoConfig(
project_name="Test",
secret_key="x" * 50,
databases={
"default": DatabaseConfig(
engine="django.db.backends.sqlite3",
name=":memory:",
)
},
)
from django_cfg.core.generation.data_generators.database import DatabaseSettingsGenerator
generator = DatabaseSettingsGenerator(config)
settings = generator.generate()
assert "DATABASES" in settings
assert "default" in settings["DATABASES"]
assert settings["DATABASES"]["default"]["ENGINE"] == "django.db.backends.sqlite3"Best Practices
1. Single Responsibility
Each generator should focus on one category:
- ✅
DatabaseSettingsGenerator- only database settings - ❌ Don’t mix database + cache in one generator
2. No Side Effects
Generators should be pure functions:
# ✅ Good - no side effects
def generate(self) -> Dict[str, Any]:
return {"SETTING": self.config.value}
# ❌ Bad - side effects
def generate(self) -> Dict[str, Any]:
self.config.value = "changed" # Don't modify config!
logging.info("Generating...") # Avoid I/O if possible
return {"SETTING": self.config.value}3. Type Safety
Always use type hints:
# ✅ Good
def generate(self) -> Dict[str, Any]:
settings: Dict[str, Any] = {}
return settings
# ❌ Bad
def generate(self):
settings = {}
return settings4. Error Handling
Provide context in errors:
from django_cfg.core.exceptions import ConfigurationError
try:
value = self.config.required_field
except AttributeError:
raise ConfigurationError(
"Required field missing",
context={"config": self.config.model_dump()},
suggestions=["Add the required_field to your config"],
)See Also
- Builder Pattern - How components are built
- Architecture - Overall system architecture
- Configuration - Configuration models