django-cfg 1.1.82__py3-none-any.whl → 1.2.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (244) hide show
  1. django_cfg/__init__.py +20 -448
  2. django_cfg/apps/accounts/README.md +3 -3
  3. django_cfg/apps/accounts/admin/__init__.py +0 -2
  4. django_cfg/apps/accounts/admin/activity.py +2 -9
  5. django_cfg/apps/accounts/admin/filters.py +0 -42
  6. django_cfg/apps/accounts/admin/inlines.py +8 -8
  7. django_cfg/apps/accounts/admin/otp.py +5 -5
  8. django_cfg/apps/accounts/admin/registration_source.py +1 -8
  9. django_cfg/apps/accounts/admin/user.py +12 -20
  10. django_cfg/apps/accounts/managers/user_manager.py +2 -129
  11. django_cfg/apps/accounts/migrations/0006_remove_twilioresponse_otp_secret_and_more.py +46 -0
  12. django_cfg/apps/accounts/models.py +3 -123
  13. django_cfg/apps/accounts/serializers/otp.py +40 -44
  14. django_cfg/apps/accounts/serializers/profile.py +0 -2
  15. django_cfg/apps/accounts/services/otp_service.py +98 -186
  16. django_cfg/apps/accounts/signals.py +25 -15
  17. django_cfg/apps/accounts/utils/auth_email_service.py +84 -0
  18. django_cfg/apps/accounts/views/otp.py +35 -36
  19. django_cfg/apps/agents/README.md +129 -0
  20. django_cfg/apps/agents/__init__.py +68 -0
  21. django_cfg/apps/agents/admin/__init__.py +17 -0
  22. django_cfg/apps/agents/admin/execution_admin.py +460 -0
  23. django_cfg/apps/agents/admin/registry_admin.py +360 -0
  24. django_cfg/apps/agents/admin/toolsets_admin.py +482 -0
  25. django_cfg/apps/agents/apps.py +29 -0
  26. django_cfg/apps/agents/core/__init__.py +20 -0
  27. django_cfg/apps/agents/core/agent.py +281 -0
  28. django_cfg/apps/agents/core/dependencies.py +154 -0
  29. django_cfg/apps/agents/core/exceptions.py +66 -0
  30. django_cfg/apps/agents/core/models.py +106 -0
  31. django_cfg/apps/agents/core/orchestrator.py +391 -0
  32. django_cfg/apps/agents/examples/__init__.py +3 -0
  33. django_cfg/apps/agents/examples/simple_example.py +161 -0
  34. django_cfg/apps/agents/integration/__init__.py +14 -0
  35. django_cfg/apps/agents/integration/middleware.py +80 -0
  36. django_cfg/apps/agents/integration/registry.py +345 -0
  37. django_cfg/apps/agents/integration/signals.py +50 -0
  38. django_cfg/apps/agents/management/__init__.py +3 -0
  39. django_cfg/apps/agents/management/commands/__init__.py +3 -0
  40. django_cfg/apps/agents/management/commands/create_agent.py +365 -0
  41. django_cfg/apps/agents/management/commands/orchestrator_status.py +191 -0
  42. django_cfg/apps/agents/managers/__init__.py +23 -0
  43. django_cfg/apps/agents/managers/execution.py +236 -0
  44. django_cfg/apps/agents/managers/registry.py +254 -0
  45. django_cfg/apps/agents/managers/toolsets.py +496 -0
  46. django_cfg/apps/agents/migrations/0001_initial.py +286 -0
  47. django_cfg/apps/agents/migrations/__init__.py +5 -0
  48. django_cfg/apps/agents/models/__init__.py +15 -0
  49. django_cfg/apps/agents/models/execution.py +215 -0
  50. django_cfg/apps/agents/models/registry.py +220 -0
  51. django_cfg/apps/agents/models/toolsets.py +305 -0
  52. django_cfg/apps/agents/patterns/__init__.py +24 -0
  53. django_cfg/apps/agents/patterns/content_agents.py +234 -0
  54. django_cfg/apps/agents/toolsets/__init__.py +15 -0
  55. django_cfg/apps/agents/toolsets/cache_toolset.py +285 -0
  56. django_cfg/apps/agents/toolsets/django_toolset.py +220 -0
  57. django_cfg/apps/agents/toolsets/file_toolset.py +324 -0
  58. django_cfg/apps/agents/toolsets/orm_toolset.py +319 -0
  59. django_cfg/apps/agents/urls.py +46 -0
  60. django_cfg/apps/knowbase/README.md +150 -0
  61. django_cfg/apps/knowbase/__init__.py +27 -0
  62. django_cfg/apps/knowbase/admin/__init__.py +23 -0
  63. django_cfg/apps/knowbase/admin/archive_admin.py +857 -0
  64. django_cfg/apps/knowbase/admin/chat_admin.py +386 -0
  65. django_cfg/apps/knowbase/admin/document_admin.py +650 -0
  66. django_cfg/apps/knowbase/admin/external_data_admin.py +685 -0
  67. django_cfg/apps/knowbase/apps.py +81 -0
  68. django_cfg/apps/knowbase/config/README.md +176 -0
  69. django_cfg/apps/knowbase/config/__init__.py +51 -0
  70. django_cfg/apps/knowbase/config/constance_fields.py +186 -0
  71. django_cfg/apps/knowbase/config/constance_settings.py +200 -0
  72. django_cfg/apps/knowbase/config/settings.py +450 -0
  73. django_cfg/apps/knowbase/examples/__init__.py +3 -0
  74. django_cfg/apps/knowbase/examples/external_data_usage.py +191 -0
  75. django_cfg/apps/knowbase/management/__init__.py +0 -0
  76. django_cfg/apps/knowbase/management/commands/__init__.py +0 -0
  77. django_cfg/apps/knowbase/management/commands/knowbase_stats.py +158 -0
  78. django_cfg/apps/knowbase/management/commands/setup_knowbase.py +59 -0
  79. django_cfg/apps/knowbase/managers/__init__.py +22 -0
  80. django_cfg/apps/knowbase/managers/archive.py +426 -0
  81. django_cfg/apps/knowbase/managers/base.py +32 -0
  82. django_cfg/apps/knowbase/managers/chat.py +141 -0
  83. django_cfg/apps/knowbase/managers/document.py +203 -0
  84. django_cfg/apps/knowbase/managers/external_data.py +471 -0
  85. django_cfg/apps/knowbase/migrations/0001_initial.py +427 -0
  86. django_cfg/apps/knowbase/migrations/0002_archiveitem_archiveitemchunk_documentarchive_and_more.py +434 -0
  87. django_cfg/apps/knowbase/migrations/__init__.py +5 -0
  88. django_cfg/apps/knowbase/mixins/__init__.py +15 -0
  89. django_cfg/apps/knowbase/mixins/config.py +108 -0
  90. django_cfg/apps/knowbase/mixins/creator.py +81 -0
  91. django_cfg/apps/knowbase/mixins/examples/vehicle_model_example.py +199 -0
  92. django_cfg/apps/knowbase/mixins/external_data_mixin.py +813 -0
  93. django_cfg/apps/knowbase/mixins/service.py +362 -0
  94. django_cfg/apps/knowbase/models/__init__.py +41 -0
  95. django_cfg/apps/knowbase/models/archive.py +599 -0
  96. django_cfg/apps/knowbase/models/base.py +58 -0
  97. django_cfg/apps/knowbase/models/chat.py +157 -0
  98. django_cfg/apps/knowbase/models/document.py +267 -0
  99. django_cfg/apps/knowbase/models/external_data.py +376 -0
  100. django_cfg/apps/knowbase/serializers/__init__.py +68 -0
  101. django_cfg/apps/knowbase/serializers/archive_serializers.py +386 -0
  102. django_cfg/apps/knowbase/serializers/chat_serializers.py +137 -0
  103. django_cfg/apps/knowbase/serializers/document_serializers.py +94 -0
  104. django_cfg/apps/knowbase/serializers/external_data_serializers.py +256 -0
  105. django_cfg/apps/knowbase/serializers/public_serializers.py +74 -0
  106. django_cfg/apps/knowbase/services/__init__.py +40 -0
  107. django_cfg/apps/knowbase/services/archive/__init__.py +42 -0
  108. django_cfg/apps/knowbase/services/archive/archive_service.py +541 -0
  109. django_cfg/apps/knowbase/services/archive/chunking_service.py +791 -0
  110. django_cfg/apps/knowbase/services/archive/exceptions.py +52 -0
  111. django_cfg/apps/knowbase/services/archive/extraction_service.py +508 -0
  112. django_cfg/apps/knowbase/services/archive/vectorization_service.py +362 -0
  113. django_cfg/apps/knowbase/services/base.py +53 -0
  114. django_cfg/apps/knowbase/services/chat_service.py +239 -0
  115. django_cfg/apps/knowbase/services/document_service.py +144 -0
  116. django_cfg/apps/knowbase/services/embedding/__init__.py +43 -0
  117. django_cfg/apps/knowbase/services/embedding/async_processor.py +244 -0
  118. django_cfg/apps/knowbase/services/embedding/batch_processor.py +250 -0
  119. django_cfg/apps/knowbase/services/embedding/batch_result.py +61 -0
  120. django_cfg/apps/knowbase/services/embedding/models.py +229 -0
  121. django_cfg/apps/knowbase/services/embedding/processors.py +148 -0
  122. django_cfg/apps/knowbase/services/embedding/utils.py +176 -0
  123. django_cfg/apps/knowbase/services/prompt_builder.py +191 -0
  124. django_cfg/apps/knowbase/services/search_service.py +293 -0
  125. django_cfg/apps/knowbase/signals/__init__.py +21 -0
  126. django_cfg/apps/knowbase/signals/archive_signals.py +211 -0
  127. django_cfg/apps/knowbase/signals/chat_signals.py +37 -0
  128. django_cfg/apps/knowbase/signals/document_signals.py +143 -0
  129. django_cfg/apps/knowbase/signals/external_data_signals.py +157 -0
  130. django_cfg/apps/knowbase/tasks/__init__.py +39 -0
  131. django_cfg/apps/knowbase/tasks/archive_tasks.py +316 -0
  132. django_cfg/apps/knowbase/tasks/document_processing.py +341 -0
  133. django_cfg/apps/knowbase/tasks/external_data_tasks.py +341 -0
  134. django_cfg/apps/knowbase/tasks/maintenance.py +195 -0
  135. django_cfg/apps/knowbase/urls.py +43 -0
  136. django_cfg/apps/knowbase/utils/__init__.py +12 -0
  137. django_cfg/apps/knowbase/utils/chunk_settings.py +261 -0
  138. django_cfg/apps/knowbase/utils/text_processing.py +375 -0
  139. django_cfg/apps/knowbase/utils/validation.py +99 -0
  140. django_cfg/apps/knowbase/views/__init__.py +28 -0
  141. django_cfg/apps/knowbase/views/archive_views.py +469 -0
  142. django_cfg/apps/knowbase/views/base.py +49 -0
  143. django_cfg/apps/knowbase/views/chat_views.py +181 -0
  144. django_cfg/apps/knowbase/views/document_views.py +183 -0
  145. django_cfg/apps/knowbase/views/public_views.py +129 -0
  146. django_cfg/apps/leads/admin.py +70 -0
  147. django_cfg/apps/newsletter/admin.py +234 -0
  148. django_cfg/apps/newsletter/admin_filters.py +124 -0
  149. django_cfg/apps/support/admin.py +196 -0
  150. django_cfg/apps/support/admin_filters.py +71 -0
  151. django_cfg/apps/support/templates/support/chat/ticket_chat.html +1 -1
  152. django_cfg/apps/urls.py +5 -4
  153. django_cfg/cli/README.md +1 -1
  154. django_cfg/cli/commands/create_project.py +2 -2
  155. django_cfg/cli/commands/info.py +1 -1
  156. django_cfg/config.py +44 -0
  157. django_cfg/core/config.py +29 -82
  158. django_cfg/core/environment.py +1 -1
  159. django_cfg/core/generation.py +19 -107
  160. django_cfg/{integration.py → core/integration.py} +18 -16
  161. django_cfg/core/validation.py +1 -1
  162. django_cfg/management/__init__.py +1 -1
  163. django_cfg/management/commands/__init__.py +1 -1
  164. django_cfg/management/commands/auto_generate.py +482 -0
  165. django_cfg/management/commands/migrator.py +19 -101
  166. django_cfg/management/commands/test_email.py +1 -1
  167. django_cfg/middleware/README.md +0 -158
  168. django_cfg/middleware/__init__.py +0 -2
  169. django_cfg/middleware/user_activity.py +3 -3
  170. django_cfg/models/api.py +145 -0
  171. django_cfg/models/base.py +287 -0
  172. django_cfg/models/cache.py +4 -4
  173. django_cfg/models/constance.py +25 -88
  174. django_cfg/models/database.py +9 -9
  175. django_cfg/models/drf.py +3 -36
  176. django_cfg/models/email.py +163 -0
  177. django_cfg/models/environment.py +276 -0
  178. django_cfg/models/limits.py +1 -1
  179. django_cfg/models/logging.py +366 -0
  180. django_cfg/models/revolution.py +41 -2
  181. django_cfg/models/security.py +125 -0
  182. django_cfg/models/services.py +1 -1
  183. django_cfg/modules/__init__.py +2 -56
  184. django_cfg/modules/base.py +78 -52
  185. django_cfg/modules/django_currency/service.py +2 -2
  186. django_cfg/modules/django_email.py +2 -2
  187. django_cfg/modules/django_health.py +267 -0
  188. django_cfg/modules/django_llm/llm/client.py +91 -19
  189. django_cfg/modules/django_llm/translator/translator.py +2 -2
  190. django_cfg/modules/django_logger.py +2 -2
  191. django_cfg/modules/django_ngrok.py +2 -2
  192. django_cfg/modules/django_tasks.py +68 -3
  193. django_cfg/modules/django_telegram.py +3 -3
  194. django_cfg/modules/django_twilio/sendgrid_service.py +2 -2
  195. django_cfg/modules/django_twilio/service.py +2 -2
  196. django_cfg/modules/django_twilio/simple_service.py +2 -2
  197. django_cfg/modules/django_twilio/twilio_service.py +2 -2
  198. django_cfg/modules/django_unfold/__init__.py +69 -0
  199. django_cfg/modules/{unfold → django_unfold}/callbacks.py +23 -22
  200. django_cfg/modules/django_unfold/dashboard.py +278 -0
  201. django_cfg/modules/django_unfold/icons/README.md +145 -0
  202. django_cfg/modules/django_unfold/icons/__init__.py +12 -0
  203. django_cfg/modules/django_unfold/icons/constants.py +2851 -0
  204. django_cfg/modules/django_unfold/icons/generate_icons.py +486 -0
  205. django_cfg/modules/django_unfold/models/__init__.py +42 -0
  206. django_cfg/modules/django_unfold/models/config.py +601 -0
  207. django_cfg/modules/django_unfold/models/dashboard.py +206 -0
  208. django_cfg/modules/django_unfold/models/dropdown.py +40 -0
  209. django_cfg/modules/django_unfold/models/navigation.py +73 -0
  210. django_cfg/modules/django_unfold/models/tabs.py +25 -0
  211. django_cfg/modules/{unfold → django_unfold}/system_monitor.py +2 -2
  212. django_cfg/modules/django_unfold/utils.py +140 -0
  213. django_cfg/registry/__init__.py +23 -0
  214. django_cfg/registry/core.py +61 -0
  215. django_cfg/registry/exceptions.py +11 -0
  216. django_cfg/registry/modules.py +12 -0
  217. django_cfg/registry/services.py +26 -0
  218. django_cfg/registry/third_party.py +52 -0
  219. django_cfg/routing/__init__.py +19 -0
  220. django_cfg/routing/callbacks.py +198 -0
  221. django_cfg/routing/routers.py +48 -0
  222. django_cfg/templates/admin/layouts/dashboard_with_tabs.html +8 -9
  223. django_cfg/templatetags/__init__.py +0 -0
  224. django_cfg/templatetags/django_cfg.py +33 -0
  225. django_cfg/urls.py +33 -0
  226. django_cfg/utils/path_resolution.py +1 -1
  227. django_cfg/utils/smart_defaults.py +7 -61
  228. django_cfg/utils/toolkit.py +663 -0
  229. {django_cfg-1.1.82.dist-info → django_cfg-1.2.1.dist-info}/METADATA +83 -86
  230. django_cfg-1.2.1.dist-info/RECORD +441 -0
  231. django_cfg/archive/django_sample.zip +0 -0
  232. django_cfg/models/unfold.py +0 -271
  233. django_cfg/modules/unfold/__init__.py +0 -29
  234. django_cfg/modules/unfold/dashboard.py +0 -318
  235. django_cfg/pyproject.toml +0 -370
  236. django_cfg/routers.py +0 -83
  237. django_cfg-1.1.82.dist-info/RECORD +0 -278
  238. /django_cfg/{exceptions.py → core/exceptions.py} +0 -0
  239. /django_cfg/modules/{unfold → django_unfold}/models.py +0 -0
  240. /django_cfg/modules/{unfold → django_unfold}/tailwind.py +0 -0
  241. /django_cfg/{version_check.py → utils/version_check.py} +0 -0
  242. {django_cfg-1.1.82.dist-info → django_cfg-1.2.1.dist-info}/WHEEL +0 -0
  243. {django_cfg-1.1.82.dist-info → django_cfg-1.2.1.dist-info}/entry_points.txt +0 -0
  244. {django_cfg-1.1.82.dist-info → django_cfg-1.2.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,663 @@
1
+ """
2
+ ConfigToolkit - Amazing Django Configuration Experience
3
+
4
+ The main interface for type-safe, environment-aware Django configuration.
5
+ """
6
+
7
+ import os
8
+ import time
9
+ import logging
10
+ from pathlib import Path
11
+ from typing import Dict, Any, Optional, Type, TypeVar
12
+ from threading import Lock
13
+
14
+ from ..models.environment import EnvironmentConfig
15
+ from ..models.database import DatabaseConfig
16
+ from ..models.security import SecurityConfig
17
+ from ..models.api import APIConfig
18
+ from ..models.cache import CacheConfig
19
+ from ..models.email import EmailConfig
20
+ from ..modules.django_unfold.models.config import UnfoldConfig
21
+ from ..models.constance import ConstanceConfig
22
+ from ..models.logging import LoggingConfig
23
+
24
+ logger = logging.getLogger(__name__)
25
+
26
+ T = TypeVar('T')
27
+
28
+
29
+ class ConfigToolkit:
30
+ """
31
+ 🚀 ConfigToolkit - Amazing Django Configuration Experience
32
+
33
+ Features:
34
+ - Type-safe configuration access with properties
35
+ - Automatic environment detection
36
+ - One-line Django settings integration
37
+ - Smart defaults and validation
38
+ - Amazing developer experience
39
+
40
+ Usage:
41
+ # Django settings.py
42
+ from django_cfg import ConfigToolkit
43
+ globals().update(ConfigToolkit.get_django_settings())
44
+
45
+ # Anywhere in your code
46
+ if ConfigToolkit.debug:
47
+ print("Debug mode active")
48
+
49
+ db_url = ConfigToolkit.database_url
50
+ page_size = ConfigToolkit.api_page_size
51
+ """
52
+
53
+ _instance: Optional['ConfigToolkit'] = None
54
+ _lock = Lock()
55
+ _initialized = False
56
+
57
+ # Configuration instances
58
+ _env_config: Optional[EnvironmentConfig] = None
59
+ _db_config: Optional[DatabaseConfig] = None
60
+ _security_config: Optional[SecurityConfig] = None
61
+ _api_config: Optional[APIConfig] = None
62
+ _cache_config: Optional[CacheConfig] = None
63
+ _email_config: Optional[EmailConfig] = None
64
+ _unfold_config: Optional[UnfoldConfig] = None
65
+ # Revolution config removed - use django_revolution directly
66
+ _constance_config: Optional[ConstanceConfig] = None
67
+ _logging_config: Optional[LoggingConfig] = None
68
+
69
+ # Performance tracking
70
+ _init_time_ms = 0
71
+ _config_cache = {}
72
+
73
+ def __new__(cls, *args, **kwargs):
74
+ """Singleton pattern for configuration."""
75
+ if cls._instance is None:
76
+ with cls._lock:
77
+ if cls._instance is None:
78
+ cls._instance = super().__new__(cls)
79
+ return cls._instance
80
+
81
+ def __init__(self,
82
+ database_config: Optional[DatabaseConfig] = None,
83
+ security_config: Optional[SecurityConfig] = None,
84
+ cache_config: Optional[CacheConfig] = None,
85
+ email_config: Optional[EmailConfig] = None,
86
+ unfold_config: Optional[UnfoldConfig] = None,
87
+ constance_config: Optional[ConstanceConfig] = None,
88
+ logging_config: Optional[LoggingConfig] = None):
89
+ """
90
+ Initialize ConfigToolkit with configuration models.
91
+
92
+ Args:
93
+ database_config: Custom database configuration
94
+ security_config: Custom security configuration
95
+ cache_config: Custom cache configuration
96
+ email_config: Custom email configuration
97
+ unfold_config: Custom Unfold configuration
98
+ constance_config: Custom Constance configuration
99
+ logging_config: Custom logging configuration
100
+ """
101
+ if self._initialized:
102
+ return
103
+
104
+ start_time = time.perf_counter()
105
+
106
+ try:
107
+ # Load configurations (use provided configs or create defaults)
108
+ self._load_configurations(
109
+ database_config=database_config,
110
+ security_config=security_config,
111
+ cache_config=cache_config,
112
+ email_config=email_config,
113
+ unfold_config=unfold_config,
114
+ constance_config=constance_config,
115
+ logging_config=logging_config,
116
+ )
117
+
118
+ # Configure security based on environment
119
+ self._configure_security()
120
+
121
+ # Cache performance info
122
+ self._init_time_ms = (time.perf_counter() - start_time) * 1000
123
+ self._initialized = True
124
+
125
+ # Show developer-friendly info
126
+ if self.debug:
127
+ print(f"🚀 ConfigToolkit initialized in {self._init_time_ms:.2f}ms")
128
+ print(f"🌍 Environment: {self.environment}")
129
+
130
+ except Exception as e:
131
+ logger.error(f"❌ ConfigToolkit initialization failed: {e}")
132
+ raise
133
+
134
+ def _load_configurations(self,
135
+ database_config: Optional[DatabaseConfig] = None,
136
+ security_config: Optional[SecurityConfig] = None,
137
+ cache_config: Optional[CacheConfig] = None,
138
+ email_config: Optional[EmailConfig] = None,
139
+ unfold_config: Optional[UnfoldConfig] = None,
140
+ constance_config: Optional[ConstanceConfig] = None,
141
+ logging_config: Optional[LoggingConfig] = None):
142
+ """Load all Pydantic configuration models."""
143
+ # Core configurations (always loaded)
144
+ self._env_config = EnvironmentConfig()
145
+ self._db_config = database_config or DatabaseConfig()
146
+ self._security_config = security_config or SecurityConfig()
147
+ self._api_config = APIConfig() # Keep default for now
148
+ self._cache_config = cache_config or CacheConfig()
149
+ self._email_config = email_config or EmailConfig()
150
+
151
+ # Extended configurations (optional, loaded if dependencies available)
152
+ self._load_extended_configurations(
153
+ unfold_config=unfold_config,
154
+ constance_config=constance_config,
155
+ logging_config=logging_config,
156
+ )
157
+
158
+ logger.info("✅ All configuration models loaded")
159
+
160
+ def _load_extended_configurations(self,
161
+ unfold_config: Optional[UnfoldConfig] = None,
162
+ constance_config: Optional[ConstanceConfig] = None,
163
+ logging_config: Optional[LoggingConfig] = None):
164
+ """Load extended configurations if dependencies are available."""
165
+ config_count = 6 # Core configs
166
+
167
+ # Unfold configuration
168
+ if unfold_config:
169
+ self._unfold_config = unfold_config
170
+ config_count += 1
171
+ logger.info("✅ Custom Unfold configuration loaded")
172
+ else:
173
+ self._unfold_config = UnfoldConfig()
174
+ config_count += 1
175
+ logger.info("✅ Default Unfold configuration loaded")
176
+
177
+ # Revolution config removed - configure directly in Django settings
178
+
179
+ # Constance configuration
180
+ if constance_config:
181
+ self._constance_config = constance_config
182
+ config_count += 1
183
+ logger.info("✅ Custom Constance configuration loaded")
184
+ else:
185
+ self._constance_config = ConstanceConfig()
186
+ config_count += 1
187
+ logger.info("✅ Default Constance configuration loaded")
188
+
189
+ # Logging configuration (always available)
190
+ self._logging_config = logging_config or LoggingConfig()
191
+ config_count += 1
192
+
193
+ self._config_count = config_count
194
+
195
+ def _configure_security(self):
196
+ """Configure security settings based on environment."""
197
+ if self._env_config.is_production:
198
+ self._security_config.configure_for_production()
199
+ else:
200
+ self._security_config.configure_for_development()
201
+
202
+ # ===============================================
203
+ # 🔥 CLASS METHODS - Main API
204
+ # ===============================================
205
+
206
+ @classmethod
207
+ def get_django_settings(cls) -> Dict[str, Any]:
208
+ """
209
+ 🔥 Get complete Django settings dictionary
210
+
211
+ This is the main method for Django integration.
212
+ Use in settings.py like this:
213
+
214
+ from django_cfg import ConfigToolkit
215
+ globals().update(ConfigToolkit.get_django_settings())
216
+ """
217
+ instance = cls()
218
+ settings = {}
219
+
220
+ # Merge all configuration settings
221
+ settings.update(instance._env_config.to_django_settings())
222
+ settings.update(instance._db_config.to_django_settings())
223
+ settings.update(instance._security_config.to_django_settings())
224
+ settings.update(instance._api_config.to_django_settings())
225
+ settings.update(instance._cache_config.to_django_settings())
226
+ settings.update(instance._email_config.to_django_settings())
227
+
228
+ # Extended configurations
229
+ if instance._unfold_config:
230
+ settings.update(instance._unfold_config.to_django_settings())
231
+
232
+ # Revolution settings applied directly in Django settings
233
+
234
+ if instance._constance_config:
235
+ settings.update(instance._constance_config.to_django_settings())
236
+
237
+ if instance._logging_config:
238
+ settings.update(instance._logging_config.to_django_settings())
239
+
240
+ # Add third-party apps to INSTALLED_APPS if needed
241
+ cls._extend_installed_apps(settings)
242
+ cls._extend_middleware(settings)
243
+ cls._extend_templates(settings)
244
+
245
+ return settings
246
+
247
+ @classmethod
248
+ def _extend_installed_apps(cls, settings: Dict[str, Any]):
249
+ """Extend INSTALLED_APPS with required third-party packages."""
250
+ installed_apps = settings.get('INSTALLED_APPS', [])
251
+
252
+ # Add common third-party apps
253
+ third_party_apps = [
254
+ 'rest_framework',
255
+ 'rest_framework.authtoken',
256
+ 'rest_framework_simplejwt',
257
+ 'django_filters',
258
+ 'corsheaders',
259
+ ]
260
+
261
+ # Add API documentation if enabled
262
+ instance = cls()
263
+ if instance._api_config.docs_enabled:
264
+ third_party_apps.extend([
265
+ 'drf_spectacular',
266
+ 'drf_spectacular_sidecar',
267
+ ])
268
+
269
+ # Handle special Unfold apps that need to be BEFORE django.contrib.admin
270
+ unfold_apps = []
271
+ if '_UNFOLD_APPS' in settings:
272
+ unfold_apps = settings['_UNFOLD_APPS']
273
+ del settings['_UNFOLD_APPS']
274
+
275
+ # Add other extended apps
276
+ for app_key in ['_REVOLUTION_APPS', '_CONSTANCE_APPS']:
277
+ if app_key in settings:
278
+ third_party_apps.extend(settings[app_key])
279
+ del settings[app_key] # Remove helper key
280
+
281
+ # Insert Unfold apps BEFORE django.contrib.admin
282
+ if unfold_apps:
283
+ admin_index = None
284
+ for i, app in enumerate(installed_apps):
285
+ if app == 'django.contrib.admin':
286
+ admin_index = i
287
+ break
288
+
289
+ if admin_index is not None:
290
+ # Insert unfold apps before admin
291
+ for app in reversed(unfold_apps):
292
+ if app not in installed_apps:
293
+ installed_apps.insert(admin_index, app)
294
+ else:
295
+ # If no admin app found, add at the beginning
296
+ for app in unfold_apps:
297
+ if app not in installed_apps:
298
+ installed_apps.insert(0, app)
299
+
300
+ # Add other apps that aren't already present
301
+ for app in third_party_apps:
302
+ if app not in installed_apps:
303
+ installed_apps.append(app)
304
+
305
+ settings['INSTALLED_APPS'] = installed_apps
306
+
307
+ @classmethod
308
+ def _extend_middleware(cls, settings: Dict[str, Any]):
309
+ """Extend MIDDLEWARE with required middleware."""
310
+ middleware = settings.get('MIDDLEWARE', [])
311
+
312
+ # Add CORS middleware at the beginning if CORS is enabled
313
+ instance = cls()
314
+ if instance._security_config.cors_enabled:
315
+ cors_middleware = 'corsheaders.middleware.CorsMiddleware'
316
+ if cors_middleware not in middleware:
317
+ middleware.insert(0, cors_middleware)
318
+
319
+ settings['MIDDLEWARE'] = middleware
320
+
321
+ @classmethod
322
+ def _extend_templates(cls, settings: Dict[str, Any]):
323
+ """Extend TEMPLATES with django-config-toolkit template directories."""
324
+ import os
325
+ from pathlib import Path
326
+
327
+ # Get toolkit's template directory
328
+ toolkit_dir = Path(__file__).parent
329
+ template_dir = toolkit_dir / 'templates'
330
+
331
+ if template_dir.exists():
332
+ templates = settings.get('TEMPLATES', [])
333
+
334
+ # Find the first Django template backend and add our template directory
335
+ for template_config in templates:
336
+ if template_config.get('BACKEND') == 'django.template.backends.django.DjangoTemplates':
337
+ dirs = template_config.get('DIRS', [])
338
+
339
+ # Add toolkit template directory if not already present
340
+ if str(template_dir) not in [str(d) for d in dirs]:
341
+ dirs.append(str(template_dir))
342
+ template_config['DIRS'] = dirs
343
+ break
344
+
345
+ settings['TEMPLATES'] = templates
346
+
347
+ # ===============================================
348
+ # 🌍 ENVIRONMENT PROPERTIES
349
+ # ===============================================
350
+
351
+ @classmethod
352
+ @property
353
+ def debug(cls) -> bool:
354
+ """Django DEBUG setting."""
355
+ return cls()._env_config.debug
356
+
357
+ @classmethod
358
+ @property
359
+ def secret_key(cls) -> str:
360
+ """Django SECRET_KEY."""
361
+ return cls()._env_config.secret_key
362
+
363
+ @classmethod
364
+ @property
365
+ def allowed_hosts(cls) -> list:
366
+ """Django ALLOWED_HOSTS."""
367
+ return cls()._env_config.allowed_hosts
368
+
369
+ @classmethod
370
+ @property
371
+ def is_production(cls) -> bool:
372
+ """True if running in production."""
373
+ return cls()._env_config.is_production
374
+
375
+ @classmethod
376
+ @property
377
+ def is_development(cls) -> bool:
378
+ """True if running in development."""
379
+ return cls()._env_config.is_development
380
+
381
+ @classmethod
382
+ @property
383
+ def is_docker(cls) -> bool:
384
+ """True if running in Docker."""
385
+ return cls()._env_config.is_docker
386
+
387
+ @classmethod
388
+ @property
389
+ def environment(cls) -> str:
390
+ """Environment name."""
391
+ return cls()._env_config.environment
392
+
393
+ # ===============================================
394
+ # 🗄️ DATABASE PROPERTIES
395
+ # ===============================================
396
+
397
+ @classmethod
398
+ @property
399
+ def database_url(cls) -> str:
400
+ """Primary database URL."""
401
+ return cls()._db_config.database_url
402
+
403
+ @classmethod
404
+ @property
405
+ def database_max_connections(cls) -> int:
406
+ """Database max connections."""
407
+ return cls()._db_config.max_connections
408
+
409
+ @classmethod
410
+ @property
411
+ def database_engine(cls) -> str:
412
+ """Database engine type."""
413
+ return cls()._db_config.database_engine
414
+
415
+ @classmethod
416
+ @property
417
+ def is_sqlite(cls) -> bool:
418
+ """True if using SQLite."""
419
+ return cls()._db_config.is_sqlite
420
+
421
+ @classmethod
422
+ @property
423
+ def is_postgresql(cls) -> bool:
424
+ """True if using PostgreSQL."""
425
+ return cls()._db_config.is_postgresql
426
+
427
+ # ===============================================
428
+ # 🔒 SECURITY PROPERTIES
429
+ # ===============================================
430
+
431
+ @classmethod
432
+ @property
433
+ def cors_enabled(cls) -> bool:
434
+ """True if CORS is enabled."""
435
+ return cls()._security_config.cors_enabled
436
+
437
+ @classmethod
438
+ @property
439
+ def csrf_enabled(cls) -> bool:
440
+ """True if CSRF is enabled."""
441
+ return cls()._security_config.csrf_enabled
442
+
443
+ @classmethod
444
+ @property
445
+ def ssl_enabled(cls) -> bool:
446
+ """True if SSL redirect is enabled."""
447
+ return cls()._security_config.ssl_redirect
448
+
449
+ # ===============================================
450
+ # 🌐 API PROPERTIES
451
+ # ===============================================
452
+
453
+ @classmethod
454
+ @property
455
+ def api_page_size(cls) -> int:
456
+ """API pagination page size."""
457
+ return cls()._api_config.page_size
458
+
459
+ @classmethod
460
+ @property
461
+ def api_max_page_size(cls) -> int:
462
+ """API max page size."""
463
+ return cls()._api_config.max_page_size
464
+
465
+ @classmethod
466
+ @property
467
+ def api_rate_limit_enabled(cls) -> bool:
468
+ """True if API rate limiting is enabled."""
469
+ return cls()._api_config.rate_limit_enabled
470
+
471
+ @classmethod
472
+ @property
473
+ def api_docs_enabled(cls) -> bool:
474
+ """True if API docs are enabled."""
475
+ return cls()._api_config.docs_enabled
476
+
477
+ # ===============================================
478
+ # 💾 CACHE PROPERTIES
479
+ # ===============================================
480
+
481
+ @classmethod
482
+ @property
483
+ def cache_backend(cls) -> str:
484
+ """Cache backend type."""
485
+ return cls()._cache_config.backend
486
+
487
+ @classmethod
488
+ @property
489
+ def cache_timeout(cls) -> int:
490
+ """Default cache timeout."""
491
+ return cls()._cache_config.default_timeout
492
+
493
+ # ===============================================
494
+ # 🎨 UNFOLD PROPERTIES
495
+ # ===============================================
496
+
497
+ @classmethod
498
+ @property
499
+ def unfold_enabled(cls) -> bool:
500
+ """True if Unfold admin is enabled."""
501
+ return cls()._unfold_config is not None
502
+
503
+ @classmethod
504
+ @property
505
+ def site_title(cls) -> str:
506
+ """Site title from Unfold config."""
507
+ instance = cls()
508
+ return instance._unfold_config.site_title if instance._unfold_config else "Admin"
509
+
510
+ # ===============================================
511
+ # 🚀 REVOLUTION PROPERTIES
512
+ # ===============================================
513
+
514
+ @classmethod
515
+ @property
516
+ def revolution_enabled(cls) -> bool:
517
+ """True if Django Revolution is enabled."""
518
+ instance = cls()
519
+ return False # Revolution configured directly in Django settings
520
+
521
+ @classmethod
522
+ @property
523
+ def api_prefix(cls) -> str:
524
+ """API prefix from Revolution config."""
525
+ instance = cls()
526
+ return "api" # Revolution configured directly in Django settings
527
+
528
+ # ===============================================
529
+ # ⚙️ CONSTANCE PROPERTIES
530
+ # ===============================================
531
+
532
+ @classmethod
533
+ @property
534
+ def constance_enabled(cls) -> bool:
535
+ """True if Constance is enabled."""
536
+ return cls()._constance_config is not None
537
+
538
+ @classmethod
539
+ @property
540
+ def constance_backend(cls) -> str:
541
+ """Constance backend."""
542
+ instance = cls()
543
+ return instance._constance_config.backend if instance._constance_config else "database"
544
+
545
+ # ===============================================
546
+ # 📝 LOGGING PROPERTIES
547
+ # ===============================================
548
+
549
+ @classmethod
550
+ @property
551
+ def logging_enabled(cls) -> bool:
552
+ """True if logging is configured."""
553
+ return cls()._logging_config is not None
554
+
555
+ @classmethod
556
+ @property
557
+ def log_level(cls) -> str:
558
+ """Root log level."""
559
+ instance = cls()
560
+ return instance._logging_config.root_level if instance._logging_config else "INFO"
561
+
562
+ # ===============================================
563
+ # 📧 EMAIL PROPERTIES
564
+ # ===============================================
565
+
566
+ @classmethod
567
+ @property
568
+ def email_backend(cls) -> str:
569
+ """Email backend."""
570
+ return cls()._email_config.backend
571
+
572
+ @classmethod
573
+ @property
574
+ def email_host(cls) -> str:
575
+ """Email host."""
576
+ return cls()._email_config.host
577
+
578
+ @classmethod
579
+ @property
580
+ def email_from(cls) -> str:
581
+ """Default from email."""
582
+ return cls()._email_config.default_from
583
+
584
+ # ===============================================
585
+ # 🛠️ DEVELOPER EXPERIENCE METHODS
586
+ # ===============================================
587
+
588
+ @classmethod
589
+ def print_config_summary(cls):
590
+ """Print helpful configuration summary for developers."""
591
+ instance = cls()
592
+
593
+ print("🚀 Django Config Toolkit - Configuration Summary")
594
+ print("=" * 60)
595
+ print(f"🌍 Environment: {cls.environment.upper()}")
596
+ print(f"🔧 Debug: {cls.debug}")
597
+ print(f"🗄️ Database: {cls.database_engine}")
598
+ print(f"💾 Cache: {cls.cache_backend}")
599
+ print(f"📧 Email: {cls.email_backend}")
600
+ print(f"🔒 Security: CORS={cls.cors_enabled}, CSRF={cls.csrf_enabled}, SSL={cls.ssl_enabled}")
601
+ print(f"🌐 API: Docs={cls.api_docs_enabled}, Rate Limit={cls.api_rate_limit_enabled}")
602
+ print(f"⚡ Init Time: {instance._init_time_ms:.2f}ms")
603
+ print("=" * 60)
604
+ print("💡 Access anywhere: ConfigToolkit.debug, ConfigToolkit.database_url, etc.")
605
+ print("📚 Docs: https://django-config-toolkit.readthedocs.io/")
606
+ print("=" * 60)
607
+
608
+ @classmethod
609
+ def validate_configuration(cls) -> bool:
610
+ """Validate all configurations for current environment."""
611
+ try:
612
+ instance = cls()
613
+
614
+ # Validate each configuration
615
+ env_valid = instance._env_config.validate_for_environment(cls.environment)
616
+ db_valid = instance._db_config.validate_for_environment(cls.environment)
617
+
618
+ return env_valid and db_valid
619
+
620
+ except Exception as e:
621
+ print(f"❌ Configuration validation failed: {e}")
622
+ return False
623
+
624
+ @classmethod
625
+ def create_env_examples(cls):
626
+ """Create .env.example files for all configurations."""
627
+ configs = [
628
+ ('environment', EnvironmentConfig),
629
+ ('database', DatabaseConfig),
630
+ ('security', SecurityConfig),
631
+ ('api', APIConfig),
632
+ ('cache', CacheConfig),
633
+ ('email', EmailConfig),
634
+ ]
635
+
636
+ print("🚀 Creating environment configuration examples...")
637
+
638
+ for name, config_class in configs:
639
+ filename = f".env.{name}.example"
640
+ config_class.create_env_example(filename)
641
+
642
+ # Create combined example
643
+ print("📋 Creating combined .env.example...")
644
+ EnvironmentConfig.create_env_example(".env.example")
645
+
646
+ print("✅ All environment examples created!")
647
+ print("💡 Copy .env.example to .env and customize your settings")
648
+
649
+
650
+ # Convenience functions for developers
651
+ def show_config():
652
+ """Show configuration summary - helpful for debugging."""
653
+ ConfigToolkit.print_config_summary()
654
+
655
+
656
+ def validate_config() -> bool:
657
+ """Validate current configuration."""
658
+ return ConfigToolkit.validate_configuration()
659
+
660
+
661
+ def create_env_examples():
662
+ """Create .env example files."""
663
+ ConfigToolkit.create_env_examples()