Skip to main content

Registry System - Component Discovery & Management

The Registry System is Django-CFG's centralized component discovery and import management system. It provides automatic registration, lazy loading, and organized access to all Django-CFG components.

Overview

The Registry System provides:

  • 🔍 Automatic Discovery - Components register themselves automatically
  • 📦 Lazy Loading - Import components only when needed
  • 🏗️ Organized Structure - Components grouped by functionality
  • 🔌 Plugin Architecture - Easy third-party integration
  • ⚡ Performance Optimization - Efficient import management
  • 🛡️ Type Safety - Full type hints and validation

Registry Architecture

Registry Structure

Django-CFG uses multiple specialized registries:

# Combined registry structure
DJANGO_CFG_REGISTRY = {
**CORE_REGISTRY, # Core components (config, exceptions, etc.)
**SERVICES_REGISTRY, # Service integrations (email, telegram, etc.)
**THIRD_PARTY_REGISTRY, # Third-party integrations (unfold, etc.)
**MODULES_REGISTRY, # Utility modules and functions
**EXCEPTIONS_REGISTRY, # Exception classes and handlers
}

Registry Categories

1. Core Registry (CORE_REGISTRY)

Essential Django-CFG components:

CORE_REGISTRY = {
# Core configuration
"DjangoConfig": ("django_cfg.core.config", "DjangoConfig"),

# Core exceptions
"ConfigurationError": ("django_cfg.core.exceptions", "ConfigurationError"),
"ValidationError": ("django_cfg.core.exceptions", "ValidationError"),
"DatabaseError": ("django_cfg.core.exceptions", "DatabaseError"),

# Database models
"DatabaseConfig": ("django_cfg.models.database", "DatabaseConfig"),

# Cache models
"CacheConfig": ("django_cfg.models.cache", "CacheConfig"),

# Security models
"SecuritySettings": ("django_cfg.models.security", "SecuritySettings"),

# Logging models
"LoggingConfig": ("django_cfg.models.logging", "LoggingConfig"),

# JWT models
"JWTConfig": ("django_cfg.models.jwt", "JWTConfig"),

# Task models
"TaskConfig": ("django_cfg.models.tasks", "TaskConfig"),
"RearqConfig": ("django_cfg.models.tasks", "RearqConfig"),

# Utils
"version_check": ("django_cfg.utils.version_check", "version_check"),

# Routing
"DynamicRouter": ("django_cfg.routing.routers", "DynamicRouter"),
}

2. Services Registry (SERVICES_REGISTRY)

Service integrations and modules:

SERVICES_REGISTRY = {
# Email services
"EmailConfig": ("django_cfg.models.services", "EmailConfig"),
"DjangoEmailService": ("django_cfg.modules.django_email", "DjangoEmailService"),
"send_email": ("django_cfg.modules.django_email", "send_email"),

# Telegram services
"TelegramConfig": ("django_cfg.models.services", "TelegramConfig"),
"DjangoTelegram": ("django_cfg.modules.django_telegram", "DjangoTelegram"),
"send_telegram_message": ("django_cfg.modules.django_telegram", "send_telegram_message"),

# Twilio services
"TwilioConfig": ("django_cfg.modules.django_twilio.models", "TwilioConfig"),
"TwilioVerifyConfig": ("django_cfg.modules.django_twilio.models", "TwilioVerifyConfig"),

# Logging services
"DjangoLogger": ("django_cfg.modules.django_logger", "DjangoLogger"),
"get_logger": ("django_cfg.modules.django_logger", "get_logger"),
}

3. Third-Party Registry (THIRD_PARTY_REGISTRY)

External integrations:

THIRD_PARTY_REGISTRY = {
# Django-CFG API Client Generation
"OpenAPIClientConfig": ("django_cfg.models.openapi_client", "OpenAPIClientConfig"),
"GroupModel": ("django_cfg.client.config", "GroupModel"),

# Unfold Admin
"UnfoldConfig": ("django_cfg.modules.django_unfold.models.config", "UnfoldConfig"),
"UnfoldTheme": ("django_cfg.modules.django_unfold.models.config", "UnfoldTheme"),
"NavigationItem": ("django_cfg.modules.django_unfold.models.navigation", "NavigationItem"),

# DRF Integration
"DRFConfig": ("django_cfg.models.drf", "DRFConfig"),
"DRFPaginationConfig": ("django_cfg.models.drf", "DRFPaginationConfig"),

# Constance Integration
"ConstanceConfig": ("django_cfg.models.constance", "ConstanceConfig"),
"ConstanceFieldConfig": ("django_cfg.models.constance", "ConstanceFieldConfig"),
}

4. Modules Registry (MODULES_REGISTRY)

Utility modules and functions:

MODULES_REGISTRY = {
# URL integration
"add_django_cfg_urls": ("django_cfg.core.integration", "add_django_cfg_urls"),
"get_django_cfg_urls_info": ("django_cfg.core.integration", "get_django_cfg_urls_info"),

# Configuration utilities
"set_current_config": ("django_cfg.core.config", "set_current_config"),

# Import/Export integration
"ImportForm": ("django_cfg.modules.django_import_export", "ImportForm"),
"ExportForm": ("django_cfg.modules.django_import_export", "ExportForm"),
"ImportExportMixin": ("django_cfg.modules.django_import_export", "ImportExportMixin"),
}

Component Discovery

Automatic Registration

Components register themselves automatically when imported:

# Component registration happens automatically
from django_cfg import DjangoConfig, EmailConfig, DjangoEmailService

# All components are now available in the registry

Manual Registration

You can also register custom components:

from django_cfg.registry import register_component

# Register custom component
@register_component("MyCustomService")
class MyCustomService:
"""Custom service implementation."""
pass

# Register with specific category
register_component("MyUtility", category="utilities")(MyUtility)

Registry Access

Access registered components programmatically:

from django_cfg.registry import get_component, list_components

# Get specific component
DjangoConfig = get_component("DjangoConfig")
EmailService = get_component("DjangoEmailService")

# List all components
all_components = list_components()

# List components by category
core_components = list_components(category="core")
service_components = list_components(category="services")

Lazy Loading System

Import Optimization

The registry uses lazy loading to optimize performance:

# Components are not imported until actually used
from django_cfg import DjangoEmailService # Module not loaded yet

# Component is loaded only when instantiated
email_service = DjangoEmailService() # Now the module is loaded

Lazy Import Implementation

class LazyImport:
"""Lazy import wrapper for registry components."""

def __init__(self, module_path: str, component_name: str):
self.module_path = module_path
self.component_name = component_name
self._component = None

def __call__(self, *args, **kwargs):
"""Import and instantiate component on first use."""
if self._component is None:
module = importlib.import_module(self.module_path)
self._component = getattr(module, self.component_name)

return self._component(*args, **kwargs)

def __getattr__(self, name):
"""Delegate attribute access to the actual component."""
if self._component is None:
module = importlib.import_module(self.module_path)
self._component = getattr(module, self.component_name)

return getattr(self._component, name)

# Usage in registry
REGISTRY = {
"DjangoEmailService": LazyImport(
"django_cfg.modules.django_email",
"DjangoEmailService"
)
}

🔌 Plugin Architecture

Plugin Registration

Create and register plugins easily:

from django_cfg.registry import register_plugin
from django_cfg.modules.base import BaseCfgModule

@register_plugin("my_custom_plugin")
class MyCustomPlugin(BaseCfgModule):
"""Custom plugin implementation."""

def __init__(self):
super().__init__()
self.config = self.get_config()

def process_data(self, data):
"""Process data using plugin logic."""
return f"Processed: {data}"

def health_check(self):
"""Plugin health check."""
return {"status": "healthy", "plugin": "my_custom_plugin"}

# Plugin is automatically available
from django_cfg import MyCustomPlugin

plugin = MyCustomPlugin()
result = plugin.process_data("test data")

Plugin Discovery

Discover and load plugins dynamically:

from django_cfg.registry import discover_plugins, load_plugin

# Discover all available plugins
plugins = discover_plugins()
print(f"Found {len(plugins)} plugins")

# Load specific plugin
plugin_class = load_plugin("my_custom_plugin")
plugin_instance = plugin_class()

# Load all plugins of a specific type
service_plugins = discover_plugins(plugin_type="service")
for plugin_name, plugin_class in service_plugins.items():
plugin = plugin_class()
print(f"Loaded service plugin: {plugin_name}")

Plugin Metadata

Add metadata to plugins for better discovery:

from django_cfg.registry import register_plugin, PluginMetadata

@register_plugin(
"advanced_email_plugin",
metadata=PluginMetadata(
name="Advanced Email Plugin",
description="Enhanced email functionality with templates",
version="1.0.0",
author="Django-CFG Team",
dependencies=["sendgrid", "jinja2"],
tags=["email", "templates", "notifications"]
)
)
class AdvancedEmailPlugin(BaseCfgModule):
"""Advanced email plugin with template support."""

def send_templated_email(self, template, context, recipients):
"""Send email using template."""
# Implementation here
pass

Registry Management

Registry Inspection

Inspect registry contents and structure:

from django_cfg.registry import inspect_registry, get_registry_stats

# Get registry statistics
stats = get_registry_stats()
print(f"Total components: {stats['total']}")
print(f"Core components: {stats['core']}")
print(f"Service components: {stats['services']}")

# Inspect specific component
component_info = inspect_registry("DjangoEmailService")
print(f"Module: {component_info['module']}")
print(f"Class: {component_info['class']}")
print(f"Category: {component_info['category']}")

# List all components with details
all_components = inspect_registry()
for name, info in all_components.items():
print(f"{name}: {info['module']}.{info['class']}")

Registry Validation

Validate registry integrity:

from django_cfg.registry import validate_registry, RegistryValidator

# Basic validation
validation_result = validate_registry()
if validation_result.is_valid:
print("Registry is valid")
else:
print(f"Registry errors: {validation_result.errors}")

# Advanced validation
validator = RegistryValidator()
validator.check_imports()
validator.check_dependencies()
validator.check_duplicates()

report = validator.generate_report()
print(report)

Registry Debugging

Debug registry issues:

from django_cfg.registry import debug_registry, RegistryDebugger

# Debug specific component
debug_info = debug_registry("DjangoEmailService")
print(f"Import path: {debug_info['import_path']}")
print(f"Is loaded: {debug_info['is_loaded']}")
print(f"Dependencies: {debug_info['dependencies']}")

# Comprehensive debugging
debugger = RegistryDebugger()
debugger.trace_imports()
debugger.check_circular_dependencies()
debugger.analyze_load_times()

debug_report = debugger.generate_report()
print(debug_report)

Advanced Registry Features

Conditional Registration

Register components conditionally:

from django_cfg.registry import register_conditional
import sys

# Register only on specific Python versions
@register_conditional(
condition=lambda: sys.version_info >= (3, 9),
name="ModernPythonFeature"
)
class ModernPythonFeature:
"""Feature that requires Python 3.9+."""
pass

# Register based on installed packages
@register_conditional(
condition=lambda: importlib.util.find_spec("redis") is not None,
name="RedisIntegration"
)
class RedisIntegration:
"""Redis integration (only if redis is installed)."""
pass

# Register based on configuration
@register_conditional(
condition=lambda: getattr(settings, 'ENABLE_ADVANCED_FEATURES', False),
name="AdvancedFeatures"
)
class AdvancedFeatures:
"""Advanced features (only if enabled in settings)."""
pass

Registry Hooks

Add hooks for registry events:

from django_cfg.registry import add_registry_hook

@add_registry_hook("component_registered")
def on_component_registered(component_name, component_class):
"""Called when a component is registered."""
print(f"Registered component: {component_name}")

# Log to monitoring system
logger.info(f"Component registered: {component_name}")

@add_registry_hook("component_loaded")
def on_component_loaded(component_name, component_instance):
"""Called when a component is first loaded."""
print(f"Loaded component: {component_name}")

# Initialize component if needed
if hasattr(component_instance, 'initialize'):
component_instance.initialize()

@add_registry_hook("registry_ready")
def on_registry_ready():
"""Called when registry is fully initialized."""
print("Django-CFG registry is ready")

# Perform post-initialization tasks
validate_all_components()
setup_monitoring()

Registry Caching

Cache registry operations for performance:

from django_cfg.registry import RegistryCache
from functools import lru_cache

class CachedRegistry:
"""Registry with caching support."""

def __init__(self):
self.cache = RegistryCache()

@lru_cache(maxsize=128)
def get_component(self, name: str):
"""Get component with caching."""
return self.cache.get_or_load(name)

def invalidate_cache(self, name: str = None):
"""Invalidate cache for specific component or all."""
if name:
self.cache.invalidate(name)
else:
self.cache.clear()

def warm_cache(self, components: list = None):
"""Pre-load components into cache."""
components = components or self.list_all_components()
for component_name in components:
self.get_component(component_name)

# Usage
registry = CachedRegistry()
registry.warm_cache(['DjangoEmailService', 'DjangoTelegram'])

Registry Monitoring

Performance Monitoring

Monitor registry performance:

from django_cfg.registry import RegistryMonitor
import time

class RegistryPerformanceMonitor:
"""Monitor registry performance metrics."""

def __init__(self):
self.metrics = {
'load_times': {},
'access_counts': {},
'error_counts': {}
}

def track_component_load(self, component_name: str):
"""Track component loading time."""
start_time = time.time()

try:
component = get_component(component_name)
load_time = time.time() - start_time

self.metrics['load_times'][component_name] = load_time
self.metrics['access_counts'][component_name] = \
self.metrics['access_counts'].get(component_name, 0) + 1

return component

except Exception as e:
self.metrics['error_counts'][component_name] = \
self.metrics['error_counts'].get(component_name, 0) + 1
raise

def get_performance_report(self):
"""Generate performance report."""
return {
'slowest_components': sorted(
self.metrics['load_times'].items(),
key=lambda x: x[1],
reverse=True
)[:10],
'most_accessed': sorted(
self.metrics['access_counts'].items(),
key=lambda x: x[1],
reverse=True
)[:10],
'error_prone': sorted(
self.metrics['error_counts'].items(),
key=lambda x: x[1],
reverse=True
)[:10]
}

# Usage
monitor = RegistryPerformanceMonitor()
email_service = monitor.track_component_load('DjangoEmailService')
report = monitor.get_performance_report()

Health Monitoring

Monitor registry health:

from django_cfg.registry import RegistryHealthChecker

class RegistryHealthChecker:
"""Check registry health and component availability."""

def check_all_components(self):
"""Check health of all registered components."""
results = {}

for component_name in list_components():
try:
component = get_component(component_name)

# Check if component has health_check method
if hasattr(component, 'health_check'):
health_result = component.health_check()
else:
health_result = {"status": "unknown", "details": "No health check"}

results[component_name] = {
"status": "healthy",
"component_health": health_result,
"loadable": True
}

except Exception as e:
results[component_name] = {
"status": "unhealthy",
"error": str(e),
"loadable": False
}

return results

def check_dependencies(self):
"""Check component dependencies."""
dependency_issues = []

for component_name in list_components():
try:
component_info = inspect_registry(component_name)
dependencies = component_info.get('dependencies', [])

for dep in dependencies:
try:
importlib.import_module(dep)
except ImportError:
dependency_issues.append({
'component': component_name,
'missing_dependency': dep
})

except Exception as e:
dependency_issues.append({
'component': component_name,
'error': str(e)
})

return dependency_issues

# Usage
health_checker = RegistryHealthChecker()
component_health = health_checker.check_all_components()
dependency_issues = health_checker.check_dependencies()

Best Practices

1. Component Naming

Use consistent naming conventions:

# Good: Clear, descriptive names
"DjangoEmailService"
"TwilioConfig"
"UnfoldTheme"

# Bad: Unclear or inconsistent names
"EmailSvc"
"TwilioConf"
"Theme"

2. Lazy Loading

Always use lazy loading for optional components:

# Good: Lazy loading
@register_component("OptionalService", lazy=True)
class OptionalService:
pass

# Bad: Eager loading for optional components
import optional_service # Loaded even if not used

3. Error Handling

Handle registry errors gracefully:

from django_cfg.registry import get_component, ComponentNotFoundError

try:
service = get_component("MyService")
except ComponentNotFoundError:
# Fallback to default implementation
service = DefaultService()
except ImportError as e:
# Handle missing dependencies
logger.warning(f"Service unavailable: {e}")
service = None

4. Component Documentation

Document registered components:

@register_component(
"DocumentedService",
description="Service for handling complex operations",
version="1.0.0",
dependencies=["requests", "pydantic"]
)
class DocumentedService:
"""
Documented service with clear purpose and usage.

This service handles complex operations with proper
error handling and monitoring.
"""
pass

5. Testing Registry Components

Test component registration and loading:

from django.test import TestCase
from django_cfg.registry import get_component, is_registered

class RegistryTest(TestCase):
def test_component_registration(self):
"""Test that components are properly registered."""
self.assertTrue(is_registered("DjangoEmailService"))
self.assertTrue(is_registered("TwilioConfig"))

def test_component_loading(self):
"""Test that components can be loaded."""
email_service = get_component("DjangoEmailService")
self.assertIsNotNone(email_service)

def test_lazy_loading(self):
"""Test that components are loaded lazily."""
# Component should not be loaded yet
self.assertFalse(is_loaded("DjangoEmailService"))

# Load component
service = get_component("DjangoEmailService")

# Component should now be loaded
self.assertTrue(is_loaded("DjangoEmailService"))

Integration Examples

With Django Settings

Integrate registry with Django settings:

# settings.py
from django_cfg.registry import configure_registry

# Configure registry based on settings
configure_registry({
'lazy_loading': True,
'cache_components': True,
'validate_on_startup': DEBUG,
'monitor_performance': DEBUG,
})

# Register custom components from settings
DJANGO_CFG_COMPONENTS = {
'MyCustomService': 'myapp.services.MyCustomService',
'MyCustomConfig': 'myapp.config.MyCustomConfig',
}

for name, import_path in DJANGO_CFG_COMPONENTS.items():
register_component_from_path(name, import_path)

With Django Apps

Register components from Django apps:

# apps.py
from django.apps import AppConfig
from django_cfg.registry import register_component

class MyAppConfig(AppConfig):
name = 'myapp'

def ready(self):
# Register app-specific components
from .services import MyAppService
from .config import MyAppConfig

register_component("MyAppService")(MyAppService)
register_component("MyAppConfig")(MyAppConfig)

The Registry System provides the foundation for Django-CFG's modular architecture and component management! 🚀