django-cfg 1.3.11__py3-none-any.whl → 1.4.0__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 (439) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/apps/accounts/admin/inlines.py +11 -5
  3. django_cfg/apps/accounts/admin/user_admin.py +39 -16
  4. django_cfg/apps/accounts/serializers/profile.py +1 -1
  5. django_cfg/apps/accounts/services/otp_service.py +18 -11
  6. django_cfg/apps/accounts/signals.py +15 -24
  7. django_cfg/apps/accounts/utils/notifications.py +217 -358
  8. django_cfg/apps/accounts/views/otp.py +2 -2
  9. django_cfg/apps/accounts/views/webhook.py +1 -1
  10. django_cfg/apps/agents/core/django_agent.py +1 -1
  11. django_cfg/apps/api/commands/views.py +66 -83
  12. django_cfg/apps/api/health/drf_views.py +269 -0
  13. django_cfg/apps/api/health/serializers.py +45 -0
  14. django_cfg/apps/api/health/urls.py +6 -1
  15. django_cfg/apps/knowbase/admin/actions/__init__.py +13 -0
  16. django_cfg/apps/knowbase/admin/actions/visibility_actions.py +56 -0
  17. django_cfg/apps/knowbase/admin/document_admin.py +136 -270
  18. django_cfg/apps/knowbase/admin/helpers/__init__.py +17 -0
  19. django_cfg/apps/knowbase/admin/helpers/configs.py +72 -0
  20. django_cfg/apps/knowbase/admin/helpers/display_helpers.py +156 -0
  21. django_cfg/apps/knowbase/admin/helpers/statistics.py +108 -0
  22. django_cfg/apps/knowbase/config/constance_fields.py +1 -1
  23. django_cfg/apps/knowbase/config/settings.py +2 -2
  24. django_cfg/apps/knowbase/mixins/__init__.py +19 -2
  25. django_cfg/apps/knowbase/mixins/config/__init__.py +14 -0
  26. django_cfg/apps/knowbase/mixins/config/defaults.py +75 -0
  27. django_cfg/apps/knowbase/mixins/config/meta_config.py +120 -0
  28. django_cfg/apps/knowbase/mixins/creator.py +10 -10
  29. django_cfg/apps/knowbase/mixins/external_data_mixin.py +105 -403
  30. django_cfg/apps/knowbase/mixins/generators/__init__.py +16 -0
  31. django_cfg/apps/knowbase/mixins/generators/content_generator.py +218 -0
  32. django_cfg/apps/knowbase/mixins/generators/field_analyzer.py +76 -0
  33. django_cfg/apps/knowbase/mixins/generators/metadata_generator.py +124 -0
  34. django_cfg/apps/knowbase/mixins/service.py +2 -2
  35. django_cfg/apps/knowbase/services/archive/__init__.py +1 -0
  36. django_cfg/apps/knowbase/services/archive/analyzers/__init__.py +17 -0
  37. django_cfg/apps/knowbase/services/archive/analyzers/complexity_analyzer.py +33 -0
  38. django_cfg/apps/knowbase/services/archive/analyzers/purpose_detector.py +36 -0
  39. django_cfg/apps/knowbase/services/archive/analyzers/quality_analyzer.py +39 -0
  40. django_cfg/apps/knowbase/services/archive/analyzers/tag_generator.py +103 -0
  41. django_cfg/apps/knowbase/services/archive/chunking/__init__.py +19 -0
  42. django_cfg/apps/knowbase/services/archive/chunking/base.py +81 -0
  43. django_cfg/apps/knowbase/services/archive/chunking/json_chunker.py +62 -0
  44. django_cfg/apps/knowbase/services/archive/chunking/markdown_chunker.py +107 -0
  45. django_cfg/apps/knowbase/services/archive/chunking/python_chunker.py +248 -0
  46. django_cfg/apps/knowbase/services/archive/chunking/text_chunker.py +70 -0
  47. django_cfg/apps/knowbase/services/archive/chunking_service.py +110 -729
  48. django_cfg/apps/knowbase/services/archive/context/__init__.py +14 -0
  49. django_cfg/apps/knowbase/services/archive/context/builders.py +220 -0
  50. django_cfg/apps/knowbase/services/archive/context/models.py +38 -0
  51. django_cfg/apps/knowbase/services/embedding/models.py +18 -14
  52. django_cfg/apps/knowbase/services/embedding/processors.py +6 -3
  53. django_cfg/apps/knowbase/tasks/document_processing.py +11 -3
  54. django_cfg/apps/leads/tests.py +1 -1
  55. django_cfg/apps/payments/admin/api_keys_admin.py +1 -1
  56. django_cfg/apps/payments/admin/balance_admin.py +1 -1
  57. django_cfg/apps/payments/admin/currencies_admin.py +1 -1
  58. django_cfg/apps/payments/admin/payments_admin.py +1 -1
  59. django_cfg/apps/payments/admin/subscriptions_admin.py +1 -1
  60. django_cfg/apps/payments/admin_interface/templates/payments/base.html +59 -126
  61. django_cfg/apps/payments/admin_interface/views/api/payments.py +1 -1
  62. django_cfg/apps/payments/admin_interface/views/api/stats.py +1 -1
  63. django_cfg/apps/payments/admin_interface/views/api/users.py +1 -1
  64. django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +1 -1
  65. django_cfg/apps/payments/admin_interface/views/api/webhook_public.py +1 -1
  66. django_cfg/apps/payments/admin_interface/views/base.py +29 -2
  67. django_cfg/apps/payments/apps.py +1 -1
  68. django_cfg/apps/payments/config/django_cfg_integration.py +2 -2
  69. django_cfg/apps/payments/config/helpers.py +3 -2
  70. django_cfg/apps/payments/management/commands/cleanup_expired_data.py +1 -1
  71. django_cfg/apps/payments/management/commands/currency_stats.py +1 -1
  72. django_cfg/apps/payments/management/commands/manage_currencies.py +1 -1
  73. django_cfg/apps/payments/management/commands/manage_providers.py +1 -1
  74. django_cfg/apps/payments/management/commands/process_pending_payments.py +1 -1
  75. django_cfg/apps/payments/management/commands/test_providers.py +1 -1
  76. django_cfg/apps/payments/middleware/api_access.py +1 -1
  77. django_cfg/apps/payments/middleware/rate_limiting.py +1 -1
  78. django_cfg/apps/payments/middleware/usage_tracking.py +1 -1
  79. django_cfg/apps/payments/models/balance.py +2 -2
  80. django_cfg/apps/payments/models/managers/api_key_managers.py +1 -1
  81. django_cfg/apps/payments/models/managers/balance_managers.py +1 -1
  82. django_cfg/apps/payments/models/managers/currency_managers.py +1 -1
  83. django_cfg/apps/payments/models/managers/payment_managers.py +1 -1
  84. django_cfg/apps/payments/models/managers/subscription_managers.py +1 -1
  85. django_cfg/apps/payments/models/payments.py +2 -2
  86. django_cfg/apps/payments/services/cache_service/__init__.py +1 -1
  87. django_cfg/apps/payments/services/cache_service/simple_cache.py +10 -5
  88. django_cfg/apps/payments/services/core/base.py +1 -1
  89. django_cfg/apps/payments/services/core/currency/__init__.py +13 -0
  90. django_cfg/apps/payments/services/core/currency/currency_converter.py +57 -0
  91. django_cfg/apps/payments/services/core/currency/currency_validator.py +61 -0
  92. django_cfg/apps/payments/services/core/operations/__init__.py +15 -0
  93. django_cfg/apps/payments/services/core/operations/payment_canceller.py +100 -0
  94. django_cfg/apps/payments/services/core/operations/payment_creator.py +196 -0
  95. django_cfg/apps/payments/services/core/operations/status_checker.py +100 -0
  96. django_cfg/apps/payments/services/core/payment_service.py +124 -612
  97. django_cfg/apps/payments/services/core/providers/__init__.py +13 -0
  98. django_cfg/apps/payments/services/core/providers/provider_client.py +132 -0
  99. django_cfg/apps/payments/services/core/providers/status_mapper.py +89 -0
  100. django_cfg/apps/payments/services/core/utils/__init__.py +13 -0
  101. django_cfg/apps/payments/services/core/utils/data_converter.py +48 -0
  102. django_cfg/apps/payments/services/core/utils/statistics_calculator.py +69 -0
  103. django_cfg/apps/payments/services/providers/base.py +1 -1
  104. django_cfg/apps/payments/services/providers/nowpayments/__init__.py +3 -3
  105. django_cfg/apps/payments/services/providers/nowpayments/parsers/__init__.py +9 -0
  106. django_cfg/apps/payments/services/providers/nowpayments/parsers/data/__init__.py +23 -0
  107. django_cfg/apps/payments/services/providers/nowpayments/parsers/data/constants.py +23 -0
  108. django_cfg/apps/payments/services/providers/nowpayments/parsers/data/currency_names.py +244 -0
  109. django_cfg/apps/payments/services/providers/nowpayments/parsers/data/patterns.py +511 -0
  110. django_cfg/apps/payments/services/providers/nowpayments/parsers/parser.py +168 -0
  111. django_cfg/apps/payments/services/providers/nowpayments/provider.py +1 -1
  112. django_cfg/apps/payments/services/providers/nowpayments/sync.py +1 -1
  113. django_cfg/apps/payments/services/providers/registry.py +1 -1
  114. django_cfg/apps/payments/services/providers/sync_service.py +1 -1
  115. django_cfg/apps/payments/signals/__init__.py +1 -1
  116. django_cfg/apps/payments/signals/api_key_signals.py +1 -1
  117. django_cfg/apps/payments/signals/balance_signals.py +1 -1
  118. django_cfg/apps/payments/signals/payment_signals.py +1 -1
  119. django_cfg/apps/payments/signals/subscription_signals.py +1 -1
  120. django_cfg/apps/payments/views/api/api_keys.py +1 -1
  121. django_cfg/apps/payments/views/api/balances.py +1 -1
  122. django_cfg/apps/payments/views/api/base.py +1 -1
  123. django_cfg/apps/payments/views/api/currencies.py +1 -1
  124. django_cfg/apps/payments/views/api/payments.py +1 -1
  125. django_cfg/apps/payments/views/api/subscriptions.py +1 -1
  126. django_cfg/apps/payments/views/api/webhooks.py +1 -1
  127. django_cfg/apps/payments/views/serializers/api_keys.py +1 -1
  128. django_cfg/apps/payments/views/serializers/balances.py +1 -1
  129. django_cfg/apps/payments/views/serializers/currencies.py +1 -1
  130. django_cfg/apps/payments/views/serializers/payments.py +1 -1
  131. django_cfg/apps/payments/views/serializers/subscriptions.py +1 -1
  132. django_cfg/apps/payments/views/serializers/webhooks.py +1 -1
  133. django_cfg/apps/support/admin/support_admin.py +21 -13
  134. django_cfg/apps/support/templates/support/chat/access_denied.html +21 -27
  135. django_cfg/apps/support/templates/support/chat/ticket_chat.html +183 -254
  136. django_cfg/apps/support/utils/support_email_service.py +1 -1
  137. django_cfg/apps/tasks/templates/tasks/layout/base.html +20 -115
  138. django_cfg/apps/tasks/utils/simulator.py +1 -1
  139. django_cfg/apps/tasks/views/dashboard.py +33 -3
  140. django_cfg/apps/urls.py +5 -1
  141. django_cfg/cli/README.md +57 -471
  142. django_cfg/cli/commands/create_project.py +140 -529
  143. django_cfg/cli/main.py +13 -10
  144. django_cfg/core/__init__.py +63 -6
  145. django_cfg/core/base/__init__.py +5 -0
  146. django_cfg/core/base/config_model.py +652 -0
  147. django_cfg/core/builders/__init__.py +11 -0
  148. django_cfg/core/builders/apps_builder.py +258 -0
  149. django_cfg/core/builders/middleware_builder.py +115 -0
  150. django_cfg/core/builders/security_builder.py +96 -0
  151. django_cfg/core/config.py +20 -892
  152. django_cfg/core/constants.py +69 -0
  153. django_cfg/core/environment/__init__.py +9 -0
  154. django_cfg/core/exceptions.py +45 -298
  155. django_cfg/core/generation/__init__.py +51 -0
  156. django_cfg/core/generation/core_generators/__init__.py +0 -0
  157. django_cfg/core/generation/core_generators/settings.py +90 -0
  158. django_cfg/core/generation/core_generators/static.py +82 -0
  159. django_cfg/core/generation/core_generators/templates.py +141 -0
  160. django_cfg/core/generation/data_generators/__init__.py +15 -0
  161. django_cfg/core/generation/data_generators/cache.py +132 -0
  162. django_cfg/core/generation/data_generators/database.py +117 -0
  163. django_cfg/core/generation/generation.py +92 -0
  164. django_cfg/core/generation/integration_generators/__init__.py +21 -0
  165. django_cfg/core/generation/integration_generators/api.py +237 -0
  166. django_cfg/core/generation/integration_generators/sessions.py +65 -0
  167. django_cfg/core/generation/integration_generators/tailwind.py +54 -0
  168. django_cfg/core/generation/integration_generators/tasks.py +92 -0
  169. django_cfg/core/generation/integration_generators/third_party.py +144 -0
  170. django_cfg/core/generation/orchestrator.py +285 -0
  171. django_cfg/core/generation/protocols.py +30 -0
  172. django_cfg/core/generation/security_generators/__init__.py +0 -0
  173. django_cfg/core/generation/utility_generators/__init__.py +24 -0
  174. django_cfg/core/generation/utility_generators/email.py +58 -0
  175. django_cfg/core/generation/utility_generators/i18n.py +66 -0
  176. django_cfg/core/generation/utility_generators/limits.py +58 -0
  177. django_cfg/core/generation/utility_generators/logging.py +66 -0
  178. django_cfg/core/generation/utility_generators/security.py +101 -0
  179. django_cfg/core/generation/utils/__init__.py +0 -0
  180. django_cfg/core/generation/utils/helpers.py +32 -0
  181. django_cfg/core/integration/__init__.py +18 -25
  182. django_cfg/core/integration/display/startup.py +146 -133
  183. django_cfg/core/integration/url_integration.py +13 -2
  184. django_cfg/core/services/__init__.py +5 -0
  185. django_cfg/core/services/config_service.py +121 -0
  186. django_cfg/core/state/__init__.py +9 -0
  187. django_cfg/core/state/registry.py +84 -0
  188. django_cfg/core/types/__init__.py +15 -0
  189. django_cfg/core/types/aliases.py +15 -0
  190. django_cfg/core/types/enums.py +49 -0
  191. django_cfg/dashboard/DEBUG_README.md +105 -0
  192. django_cfg/dashboard/REFACTORING_SUMMARY.md +237 -0
  193. django_cfg/dashboard/__init__.py +24 -0
  194. django_cfg/dashboard/components.py +308 -0
  195. django_cfg/dashboard/debug.py +176 -0
  196. django_cfg/dashboard/management/__init__.py +0 -0
  197. django_cfg/dashboard/management/commands/__init__.py +0 -0
  198. django_cfg/dashboard/management/commands/debug_dashboard.py +109 -0
  199. django_cfg/dashboard/sections/__init__.py +1 -0
  200. django_cfg/dashboard/sections/base.py +128 -0
  201. django_cfg/dashboard/sections/commands.py +32 -0
  202. django_cfg/dashboard/sections/overview.py +394 -0
  203. django_cfg/dashboard/sections/stats.py +48 -0
  204. django_cfg/dashboard/sections/system.py +73 -0
  205. django_cfg/management/commands/check_settings.py +6 -2
  206. django_cfg/management/commands/clear_constance.py +6 -1
  207. django_cfg/management/commands/create_token.py +5 -4
  208. django_cfg/management/commands/generate.py +5 -0
  209. django_cfg/management/commands/list_urls.py +7 -2
  210. django_cfg/management/commands/migrate_all.py +6 -2
  211. django_cfg/management/commands/migrator.py +6 -1
  212. django_cfg/management/commands/rundramatiq.py +6 -1
  213. django_cfg/management/commands/rundramatiq_simulator.py +11 -4
  214. django_cfg/management/commands/runserver_ngrok.py +9 -7
  215. django_cfg/management/commands/script.py +25 -21
  216. django_cfg/management/commands/show_config.py +6 -1
  217. django_cfg/management/commands/show_urls.py +8 -3
  218. django_cfg/management/commands/superuser.py +5 -4
  219. django_cfg/management/commands/task_clear.py +8 -3
  220. django_cfg/management/commands/task_status.py +8 -3
  221. django_cfg/management/commands/test_email.py +6 -1
  222. django_cfg/management/commands/test_telegram.py +6 -1
  223. django_cfg/management/commands/test_twilio.py +6 -1
  224. django_cfg/management/commands/tree.py +7 -4
  225. django_cfg/models/__init__.py +88 -3
  226. django_cfg/models/api/__init__.py +27 -0
  227. django_cfg/models/{api.py → api/config.py} +1 -1
  228. django_cfg/models/api/drf/__init__.py +21 -0
  229. django_cfg/models/api/drf/config.py +101 -0
  230. django_cfg/models/api/drf/redoc.py +31 -0
  231. django_cfg/models/api/drf/spectacular.py +129 -0
  232. django_cfg/models/api/drf/swagger.py +59 -0
  233. django_cfg/models/{api_keys.py → api/keys.py} +16 -6
  234. django_cfg/models/{limits.py → api/limits.py} +0 -1
  235. django_cfg/models/base/__init__.py +14 -0
  236. django_cfg/models/django/__init__.py +16 -0
  237. django_cfg/models/{constance.py → django/constance.py} +1 -1
  238. django_cfg/models/{environment.py → django/environment.py} +1 -1
  239. django_cfg/models/infrastructure/__init__.py +17 -0
  240. django_cfg/models/{cache.py → infrastructure/cache.py} +3 -2
  241. django_cfg/models/infrastructure/database/__init__.py +22 -0
  242. django_cfg/models/infrastructure/database/config.py +265 -0
  243. django_cfg/models/infrastructure/database/converters.py +91 -0
  244. django_cfg/models/infrastructure/database/parsers.py +96 -0
  245. django_cfg/models/infrastructure/database/routing.py +85 -0
  246. django_cfg/models/infrastructure/database/validators.py +170 -0
  247. django_cfg/models/{logging.py → infrastructure/logging.py} +1 -1
  248. django_cfg/models/{security.py → infrastructure/security.py} +2 -2
  249. django_cfg/models/ngrok/__init__.py +11 -0
  250. django_cfg/models/ngrok/auth.py +37 -0
  251. django_cfg/models/ngrok/config.py +77 -0
  252. django_cfg/models/ngrok/tunnel.py +35 -0
  253. django_cfg/models/payments/__init__.py +20 -0
  254. django_cfg/models/payments/api_keys.py +57 -0
  255. django_cfg/models/{payments.py → payments/config.py} +56 -154
  256. django_cfg/models/payments/providers/__init__.py +15 -0
  257. django_cfg/models/payments/providers/base.py +25 -0
  258. django_cfg/models/payments/providers/nowpayments.py +48 -0
  259. django_cfg/models/services/__init__.py +18 -0
  260. django_cfg/models/services/base.py +65 -0
  261. django_cfg/models/{email.py → services/email.py} +1 -1
  262. django_cfg/models/services/telegram.py +172 -0
  263. django_cfg/models/tasks/__init__.py +51 -0
  264. django_cfg/models/tasks/backends.py +250 -0
  265. django_cfg/models/tasks/config.py +314 -0
  266. django_cfg/models/tasks/utils.py +174 -0
  267. django_cfg/modules/base.py +18 -3
  268. django_cfg/modules/django_admin/decorators/actions.py +1 -1
  269. django_cfg/modules/django_admin/decorators/display.py +1 -1
  270. django_cfg/modules/django_admin/mixins/standalone_actions_mixin.py +1 -1
  271. django_cfg/modules/django_cfg_rpc_client/README.md +346 -0
  272. django_cfg/modules/django_cfg_rpc_client/__init__.py +51 -0
  273. django_cfg/modules/django_cfg_rpc_client/client.py +540 -0
  274. django_cfg/modules/django_cfg_rpc_client/config.py +207 -0
  275. django_cfg/modules/django_cfg_rpc_client/dashboard/README.md +517 -0
  276. django_cfg/modules/django_cfg_rpc_client/dashboard/UNFOLD_INTEGRATION.md +439 -0
  277. django_cfg/modules/django_cfg_rpc_client/dashboard/__init__.py +11 -0
  278. django_cfg/modules/django_cfg_rpc_client/dashboard/apps.py +22 -0
  279. django_cfg/modules/django_cfg_rpc_client/dashboard/monitor.py +435 -0
  280. django_cfg/modules/django_cfg_rpc_client/dashboard/static/django_cfg_rpc_dashboard/js/dashboard.js +373 -0
  281. django_cfg/modules/django_cfg_rpc_client/dashboard/templates/django_cfg_rpc_dashboard/base.html +76 -0
  282. django_cfg/modules/django_cfg_rpc_client/dashboard/templates/django_cfg_rpc_dashboard/dashboard.html +200 -0
  283. django_cfg/modules/django_cfg_rpc_client/dashboard/urls.py +22 -0
  284. django_cfg/modules/django_cfg_rpc_client/dashboard/urls_admin.py +9 -0
  285. django_cfg/modules/django_cfg_rpc_client/dashboard/views.py +251 -0
  286. django_cfg/modules/django_cfg_rpc_client/exceptions.py +201 -0
  287. django_cfg/modules/django_drf_theme/CHANGELOG.md +210 -0
  288. django_cfg/modules/django_drf_theme/EXAMPLE.md +465 -0
  289. django_cfg/modules/django_drf_theme/IMPLEMENTATION.md +232 -0
  290. django_cfg/modules/django_drf_theme/README.md +207 -0
  291. django_cfg/modules/django_drf_theme/TAILWIND_CDN_GUIDE.md +274 -0
  292. django_cfg/modules/django_drf_theme/__init__.py +23 -0
  293. django_cfg/modules/django_drf_theme/apps.py +15 -0
  294. django_cfg/modules/django_drf_theme/renderers.py +58 -0
  295. django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/api.html +375 -0
  296. django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/base.html +938 -0
  297. django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/forms/filter_form.html +132 -0
  298. django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/forms/raw_data_form.html +123 -0
  299. django_cfg/modules/django_drf_theme/templatetags/__init__.py +1 -0
  300. django_cfg/modules/django_drf_theme/templatetags/tailwind_tags.py +57 -0
  301. django_cfg/modules/django_email/__init__.py +14 -0
  302. django_cfg/modules/{django_email.py → django_email/service.py} +78 -113
  303. django_cfg/modules/django_email/utils.py +40 -0
  304. django_cfg/modules/django_health/__init__.py +9 -0
  305. django_cfg/modules/{django_health.py → django_health/service.py} +23 -21
  306. django_cfg/modules/django_llm/llm/client.py +155 -550
  307. django_cfg/modules/django_llm/llm/embeddings/__init__.py +13 -0
  308. django_cfg/modules/django_llm/llm/embeddings/mock_embedder.py +106 -0
  309. django_cfg/modules/django_llm/llm/embeddings/openai_embedder.py +79 -0
  310. django_cfg/modules/django_llm/llm/models_api/__init__.py +9 -0
  311. django_cfg/modules/django_llm/llm/models_api/models_query.py +163 -0
  312. django_cfg/modules/django_llm/llm/providers/__init__.py +15 -0
  313. django_cfg/modules/django_llm/llm/providers/config_builder.py +103 -0
  314. django_cfg/modules/django_llm/llm/providers/provider_manager.py +148 -0
  315. django_cfg/modules/django_llm/llm/providers/provider_selector.py +60 -0
  316. django_cfg/modules/django_llm/llm/requests/__init__.py +15 -0
  317. django_cfg/modules/django_llm/llm/requests/cache_manager.py +170 -0
  318. django_cfg/modules/django_llm/llm/requests/chat_handler.py +199 -0
  319. django_cfg/modules/django_llm/llm/requests/embedding_handler.py +113 -0
  320. django_cfg/modules/django_llm/llm/responses/__init__.py +9 -0
  321. django_cfg/modules/django_llm/llm/responses/response_builder.py +131 -0
  322. django_cfg/modules/django_llm/llm/stats/__init__.py +9 -0
  323. django_cfg/modules/django_llm/llm/stats/stats_manager.py +107 -0
  324. django_cfg/modules/django_llm/translator/detectors/__init__.py +13 -0
  325. django_cfg/modules/django_llm/translator/detectors/language_detector.py +90 -0
  326. django_cfg/modules/django_llm/translator/detectors/script_detector.py +153 -0
  327. django_cfg/modules/django_llm/translator/stats/__init__.py +11 -0
  328. django_cfg/modules/django_llm/translator/stats/stats_tracker.py +85 -0
  329. django_cfg/modules/django_llm/translator/translator.py +150 -603
  330. django_cfg/modules/django_llm/translator/translators/__init__.py +15 -0
  331. django_cfg/modules/django_llm/translator/translators/json_translator.py +316 -0
  332. django_cfg/modules/django_llm/translator/translators/text_translator.py +139 -0
  333. django_cfg/modules/django_llm/translator/utils/__init__.py +13 -0
  334. django_cfg/modules/django_llm/translator/utils/prompt_builder.py +110 -0
  335. django_cfg/modules/django_llm/translator/utils/text_utils.py +114 -0
  336. django_cfg/modules/django_logging/FIXES_SUMMARY.md +276 -0
  337. django_cfg/modules/django_logging/LOGGING_GUIDE.md +504 -0
  338. django_cfg/modules/django_logging/__init__.py +14 -0
  339. django_cfg/modules/{django_logger.py → django_logging/django_logger.py} +13 -13
  340. django_cfg/modules/{logger.py → django_logging/logger.py} +14 -4
  341. django_cfg/modules/django_ngrok/__init__.py +39 -0
  342. django_cfg/modules/{django_ngrok.py → django_ngrok/service.py} +14 -42
  343. django_cfg/modules/django_rpc_old/POETRY.md +344 -0
  344. django_cfg/modules/django_rpc_old/README.md +397 -0
  345. django_cfg/modules/django_rpc_old/TESTING.md +358 -0
  346. django_cfg/modules/django_rpc_old/__init__.py +39 -0
  347. django_cfg/modules/django_rpc_old/client.py +531 -0
  348. django_cfg/modules/django_rpc_old/config.py +279 -0
  349. django_cfg/modules/django_rpc_old/exceptions.py +172 -0
  350. django_cfg/modules/django_tailwind/README.md +478 -0
  351. django_cfg/modules/django_tailwind/__init__.py +7 -0
  352. django_cfg/modules/django_tailwind/apps.py +10 -0
  353. django_cfg/modules/django_tailwind/templates/django_tailwind/app.html +5 -0
  354. django_cfg/modules/django_tailwind/templates/django_tailwind/base.html +117 -0
  355. django_cfg/modules/django_tailwind/templates/django_tailwind/components/navbar.html +124 -0
  356. django_cfg/modules/django_tailwind/templates/django_tailwind/components/theme_toggle.html +54 -0
  357. django_cfg/modules/django_tailwind/templates/django_tailwind/components/user_menu.html +116 -0
  358. django_cfg/modules/django_tailwind/templates/django_tailwind/simple.html +46 -0
  359. django_cfg/modules/django_tailwind/templatetags/__init__.py +1 -0
  360. django_cfg/modules/django_tailwind/templatetags/tailwind_info.py +185 -0
  361. django_cfg/modules/django_tasks/__init__.py +29 -0
  362. django_cfg/modules/django_tasks/factory.py +127 -0
  363. django_cfg/modules/{django_tasks.py → django_tasks/service.py} +45 -274
  364. django_cfg/modules/django_tasks/settings.py +107 -0
  365. django_cfg/modules/django_telegram/__init__.py +29 -0
  366. django_cfg/modules/{django_telegram.py → django_telegram/service.py} +45 -113
  367. django_cfg/modules/django_telegram/utils.py +62 -0
  368. django_cfg/modules/django_twilio/__init__.py +54 -107
  369. django_cfg/modules/django_twilio/_imports.py +30 -0
  370. django_cfg/modules/django_twilio/base.py +192 -0
  371. django_cfg/modules/django_twilio/email_otp.py +227 -0
  372. django_cfg/modules/django_twilio/sendgrid_service.py +1 -1
  373. django_cfg/modules/django_twilio/simple_service.py +1 -2
  374. django_cfg/modules/django_twilio/sms.py +94 -0
  375. django_cfg/modules/django_twilio/twilio_service.py +2 -3
  376. django_cfg/modules/django_twilio/unified.py +310 -0
  377. django_cfg/modules/django_twilio/utils.py +190 -0
  378. django_cfg/modules/django_twilio/whatsapp.py +137 -0
  379. django_cfg/modules/django_unfold/callbacks/base.py +198 -7
  380. django_cfg/modules/django_unfold/callbacks/main.py +102 -10
  381. django_cfg/modules/django_unfold/dashboard.py +65 -43
  382. django_cfg/modules/django_unfold/models/config.py +13 -12
  383. django_cfg/modules/django_unfold/models/navigation.py +8 -3
  384. django_cfg/modules/django_unfold/models/tabs.py +2 -2
  385. django_cfg/modules/django_unfold/templates/unfold/helpers/app_list.html +102 -0
  386. django_cfg/registry/core.py +24 -26
  387. django_cfg/registry/modules.py +5 -2
  388. django_cfg/registry/services.py +20 -3
  389. django_cfg/registry/third_party.py +8 -8
  390. django_cfg/static/admin/css/dashboard.css +260 -0
  391. django_cfg/static/admin/js/commands.js +171 -0
  392. django_cfg/static/admin/js/dashboard.js +126 -0
  393. django_cfg/templates/admin/components/management_commands.js +375 -0
  394. django_cfg/templates/admin/components/progress_bar.html +18 -23
  395. django_cfg/templates/admin/index.html +48 -20
  396. django_cfg/templates/admin/index_new.html +106 -0
  397. django_cfg/templates/admin/layouts/base_dashboard.html +60 -0
  398. django_cfg/templates/admin/layouts/dashboard_with_tabs.html +1 -20
  399. django_cfg/templates/admin/sections/commands_section.html +626 -0
  400. django_cfg/templates/admin/sections/overview_section.html +112 -0
  401. django_cfg/templates/admin/sections/stats_section.html +35 -0
  402. django_cfg/templates/admin/sections/system_section.html +99 -0
  403. django_cfg/templates/admin/snippets/components/CHARTS_GUIDE.md +322 -0
  404. django_cfg/templates/admin/snippets/components/activity_tracker.html +85 -47
  405. django_cfg/templates/admin/snippets/components/charts_section.html +154 -64
  406. django_cfg/templates/admin/snippets/components/django_commands.html +3 -3
  407. django_cfg/templates/admin/snippets/components/recent_activity_improved.html +25 -0
  408. django_cfg/templates/admin/snippets/components/recent_users_table.html +1 -1
  409. django_cfg/templates/admin/snippets/components/system_metrics.html +179 -93
  410. django_cfg/templates/admin/snippets/zones/zones_table.html +2 -2
  411. django_cfg/templatetags/django_cfg.py +7 -1
  412. django_cfg/utils/smart_defaults.py +4 -4
  413. django_cfg-1.4.0.dist-info/METADATA +920 -0
  414. {django_cfg-1.3.11.dist-info → django_cfg-1.4.0.dist-info}/RECORD +425 -196
  415. django_cfg/apps/accounts/utils/auth_email_service.py +0 -84
  416. django_cfg/apps/payments/services/providers/nowpayments/parsers.py +0 -879
  417. django_cfg/core/generation.py +0 -621
  418. django_cfg/management/commands/validate_config.py +0 -189
  419. django_cfg/models/database.py +0 -480
  420. django_cfg/models/drf.py +0 -272
  421. django_cfg/models/ngrok.py +0 -122
  422. django_cfg/models/services.py +0 -440
  423. django_cfg/models/tasks.py +0 -550
  424. django_cfg/modules/django_twilio/service.py +0 -942
  425. django_cfg/template_archive/django_sample.zip +0 -0
  426. django_cfg/templates/rest_framework/api.html +0 -12
  427. django_cfg/utils/toolkit.py +0 -703
  428. django_cfg-1.3.11.dist-info/METADATA +0 -1029
  429. /django_cfg/apps/accounts/management/commands/{test_otp.py → otp_test.py} +0 -0
  430. /django_cfg/core/{environment.py → environment/detector.py} +0 -0
  431. /django_cfg/models/{cors.py → api/cors.py} +0 -0
  432. /django_cfg/models/{jwt.py → api/jwt.py} +0 -0
  433. /django_cfg/models/{base.py → base/config.py} +0 -0
  434. /django_cfg/models/{cfg.py → base/module.py} +0 -0
  435. /django_cfg/models/{revolution.py → django/revolution.py} +0 -0
  436. /django_cfg/modules/{dramatiq_setup.py → django_tasks/dramatiq_setup.py} +0 -0
  437. {django_cfg-1.3.11.dist-info → django_cfg-1.4.0.dist-info}/WHEEL +0 -0
  438. {django_cfg-1.3.11.dist-info → django_cfg-1.4.0.dist-info}/entry_points.txt +0 -0
  439. {django_cfg-1.3.11.dist-info → django_cfg-1.4.0.dist-info}/licenses/LICENSE +0 -0
django_cfg/core/config.py CHANGED
@@ -1,903 +1,31 @@
1
1
  """
2
- Core DjangoConfig class for django_cfg.
2
+ Convenience re-exports for django-cfg core.
3
3
 
4
- Following CRITICAL_REQUIREMENTS.md:
5
- - No raw Dict/Any usage - everything through Pydantic models
6
- - Proper type annotations for all fields
7
- - No mutable default arguments
8
- - Comprehensive validation and error handling
4
+ Usage:
5
+ from django_cfg.core.config import DjangoConfig, EnvironmentMode
9
6
  """
10
7
 
11
- from typing import Dict, List, Optional, Any, Union
12
- from pathlib import Path
13
- from pydantic import BaseModel, Field, field_validator, model_validator, PrivateAttr
14
- from enum import Enum
15
- import os
16
- from pathlib import Path
17
- from urllib.parse import urlparse
18
-
19
- from django_cfg import (
20
- ConfigurationError, ValidationError, EnvironmentError,
21
- DatabaseConfig, CacheConfig, EmailConfig, TelegramConfig,
22
- UnfoldConfig, DRFConfig, SpectacularConfig, LimitsConfig, ApiKeys
8
+ from .base.config_model import DjangoConfig
9
+ from .types.enums import EnvironmentMode, StartupInfoMode
10
+ from .constants import DEFAULT_APPS, DEFAULT_MIDDLEWARE
11
+ from .state.registry import (
12
+ get_current_config,
13
+ set_current_config,
14
+ clear_current_config,
23
15
  )
24
- from django_cfg.models.tasks import TaskConfig
25
- from django_cfg.models.payments import PaymentsConfig
26
-
27
- # Default apps
28
- DEFAULT_APPS = [
29
- # WhiteNoise for static files (must be before django.contrib.staticfiles)
30
- "whitenoise.runserver_nostatic",
31
- # Unfold
32
- "unfold",
33
- "unfold.contrib.filters", # optional, if special filters are needed
34
- "unfold.contrib.forms", # optional, if special form elements are needed
35
- "unfold.contrib.inlines", # optional, if special inlines are needed
36
- "import_export", # django-import-export package
37
- "unfold.contrib.import_export", # optional, if django-import-export package is used
38
- "unfold.contrib.guardian", # optional, if django-guardian package is used
39
- "unfold.contrib.simple_history", # optional, if django-simple-history package is used
40
- "unfold.contrib.location_field", # optional, if django-location-field package is used
41
- "unfold.contrib.constance", # optional, if django-constance package is used
42
- # Django
43
- "django.contrib.admin",
44
- "django.contrib.auth",
45
- "django.contrib.contenttypes",
46
- "django.contrib.sessions",
47
- "django.contrib.messages",
48
- "django.contrib.staticfiles",
49
- "django.contrib.humanize",
50
- # Third-party
51
- "corsheaders",
52
- "rest_framework",
53
- "rest_framework.authtoken",
54
- "rest_framework_simplejwt",
55
- "rest_framework_simplejwt.token_blacklist",
56
- "rest_framework_nested",
57
- "rangefilter",
58
- "django_filters",
59
- "drf_spectacular",
60
- "drf_spectacular_sidecar",
61
- "django_json_widget",
62
- "django_extensions",
63
- "constance",
64
- "constance.backends.database",
65
- # Note: django_dramatiq is added conditionally when tasks are enabled
66
- # Django CFG
67
- "django_cfg",
68
- "django_revolution",
69
- ]
70
-
71
-
72
- class EnvironmentMode(str, Enum):
73
- """Environment mode enumeration."""
74
- DEVELOPMENT = "development"
75
- PRODUCTION = "production"
76
- TEST = "test"
77
-
78
- @classmethod
79
- def from_debug(cls, debug: bool) -> "EnvironmentMode":
80
- """Get environment mode from debug flag."""
81
- return cls.DEVELOPMENT if debug else cls.PRODUCTION
82
-
83
-
84
- class StartupInfoMode(str, Enum):
85
- """Startup information display mode."""
86
- NONE = "none" # Minimal info only (version, environment, critical errors)
87
- SHORT = "short" # Essential info (apps, endpoints, status, updates)
88
- FULL = "full" # Complete info (everything from old system)
89
-
90
-
91
- class DjangoConfig(BaseModel):
92
- """
93
- Base configuration class for Django projects.
94
-
95
- This is the core class that all Django project configurations inherit from.
96
- It provides type-safe configuration management with intelligent defaults
97
- and automatic Django settings generation.
98
-
99
- Key Features:
100
- - 100% type safety through Pydantic v2
101
- - Environment-aware smart defaults
102
- - Automatic Django settings generation
103
- - Zero raw dictionary usage
104
- - Comprehensive validation
105
-
106
- Example:
107
- ```python
108
- class MyProjectConfig(DjangoConfig):
109
- project_name: str = "My Project"
110
- databases: Dict[str, DatabaseConfig] = {
111
- "default": DatabaseConfig(
112
- engine="django.db.backends.postgresql",
113
- name="${DATABASE_URL:mydb}",
114
- )
115
- }
116
-
117
- config = MyProjectConfig()
118
- ```
119
- """
120
-
121
- model_config = {
122
- "validate_assignment": True,
123
- "extra": "forbid", # Forbid arbitrary fields for type safety
124
- "env_prefix": "DJANGO_",
125
- "populate_by_name": True,
126
- "validate_default": True,
127
- "str_strip_whitespace": True,
128
- }
129
-
130
- # === Environment Configuration ===
131
- env_mode: EnvironmentMode = Field(
132
- default=EnvironmentMode.PRODUCTION,
133
- description="Environment mode: development, production, or test",
134
- )
135
-
136
- # === Project Information ===
137
- project_name: str = Field(
138
- ...,
139
- description="Human-readable project name",
140
- min_length=1,
141
- max_length=100,
142
- )
143
-
144
- project_logo: str = Field(
145
- default="",
146
- description="Project logo URL",
147
- )
148
-
149
- project_version: str = Field(
150
- default="1.0.0",
151
- description="Project version",
152
- pattern=r"^\d+\.\d+\.\d+.*$",
153
- )
154
-
155
- project_description: str = Field(
156
- default="",
157
- description="Project description",
158
- max_length=500,
159
- )
160
-
161
- # === Django CFG Features ===
162
- startup_info_mode: StartupInfoMode = Field(
163
- default=StartupInfoMode.FULL,
164
- description="Startup information display mode: none (minimal), short (essential), full (complete)",
165
- )
166
-
167
- enable_support: bool = Field(
168
- default=True,
169
- description="Enable django-cfg Support application (tickets, messages, chat interface)",
170
- )
171
- enable_accounts: bool = Field(
172
- default=False,
173
- description="Enable django-cfg Accounts application (advanced user management, OTP, profiles, activity tracking)",
174
- )
175
- enable_newsletter: bool = Field(
176
- default=False,
177
- description="Enable django-cfg Newsletter application (email campaigns, subscriptions, bulk emails)",
178
- )
179
- enable_leads: bool = Field(
180
- default=False,
181
- description="Enable django-cfg Leads application (lead collection, contact forms, CRM integration)",
182
- )
183
- enable_knowbase: bool = Field(
184
- default=False,
185
- description="Enable django-cfg Knowledge Base application (documents, AI chat, embeddings, search)",
186
- )
187
- enable_agents: bool = Field(
188
- default=False,
189
- description="Enable django-cfg AI Agents application (agent definitions, executions, workflows, tools)",
190
- )
191
- enable_maintenance: bool = Field(
192
- default=False,
193
- description="Enable django-cfg Maintenance application (multi-site maintenance mode with Cloudflare)",
194
- )
195
- # === Payment System Configuration ===
196
- payments: Optional[PaymentsConfig] = Field(
197
- default=None,
198
- description="Universal payment system configuration (providers, subscriptions, API keys, billing)",
199
- )
200
-
201
- # === URLs ===
202
- site_url: str = Field(default="http://localhost:3000", description="Frontend site URL")
203
- api_url: str = Field(default="http://localhost:8000", description="Backend API URL")
204
- ticket_url: str = Field(default="{site_url}/support/ticket/{uuid}", description="Support ticket URL template. Use {site_url} and {uuid} placeholders")
205
- otp_url: str = Field(default="{site_url}/auth/otp/{code}", description="OTP verification URL template. Use {site_url} and {code} placeholders")
206
-
207
- # === Core Django Settings ===
208
- secret_key: str = Field(
209
- ...,
210
- description="Django SECRET_KEY",
211
- min_length=50,
212
- repr=False, # Don't show in repr for security
213
- )
214
-
215
- debug: bool = Field(
216
- default=False,
217
- description="Django DEBUG setting",
218
- )
219
-
220
- # allowed_hosts removed - now auto-generated from security_domains
221
-
222
- # === URL Configuration ===
223
- root_urlconf: Optional[str] = Field(
224
- default=None,
225
- description="Django ROOT_URLCONF setting",
226
- )
227
-
228
- wsgi_application: Optional[str] = Field(
229
- default=None,
230
- description="Django WSGI_APPLICATION setting",
231
- )
232
-
233
- # === Custom User Model ===
234
- auth_user_model: Optional[str] = Field(
235
- default=None,
236
- description="Custom user model (AUTH_USER_MODEL). If None and enable_accounts=True, uses 'django_cfg.apps.accounts.CustomUser'",
237
- pattern=r"^[a-zA-Z_][a-zA-Z0-9_]*\.[a-zA-Z_][a-zA-Z0-9_]*$",
238
- )
239
-
240
- # === Project Applications ===
241
- project_apps: List[str] = Field(
242
- default_factory=list,
243
- description="List of project-specific Django apps",
244
- )
245
-
246
- # === Database Configuration ===
247
- databases: Dict[str, DatabaseConfig] = Field(
248
- default_factory=dict,
249
- description="Database connections",
250
- )
251
-
252
- # === Cache Configuration ===
253
- cache_default: Optional[CacheConfig] = Field(
254
- default=None,
255
- description="Default cache backend",
256
- )
257
-
258
- cache_sessions: Optional[CacheConfig] = Field(
259
- default=None,
260
- description="Sessions cache backend",
261
- )
262
-
263
- # === Security Configuration ===
264
- security_domains: List[str] = Field(
265
- default_factory=list,
266
- description="Domains for automatic security configuration (CORS, SSL, etc.)",
267
- )
268
-
269
- ssl_redirect: Optional[bool] = Field(
270
- default=None,
271
- description="Force SSL redirect on/off (None = auto based on domains and environment)",
272
- )
273
-
274
- # === CORS Configuration ===
275
- cors_allow_headers: List[str] = Field(
276
- default_factory=lambda: [
277
- "accept",
278
- "accept-encoding",
279
- "authorization",
280
- "content-type",
281
- "dnt",
282
- "origin",
283
- "user-agent",
284
- "x-csrftoken",
285
- "x-requested-with",
286
- "x-api-key",
287
- "x-api-token",
288
- ],
289
- description="CORS allowed headers with common defaults for API usage",
290
- )
291
-
292
- # === Services Configuration ===
293
- email: Optional[EmailConfig] = Field(
294
- default=None,
295
- description="Email service configuration",
296
- )
297
-
298
- telegram: Optional[TelegramConfig] = Field(
299
- default=None,
300
- description="Telegram service configuration",
301
- )
302
-
303
- # === Admin Interface Configuration ===
304
- unfold: Optional[UnfoldConfig] = Field(
305
- default=None,
306
- description="Unfold admin interface configuration",
307
- )
308
-
309
- # === Background Task Processing ===
310
- tasks: Optional[TaskConfig] = Field(
311
- default=None,
312
- description="Background task processing configuration (Dramatiq)",
313
- )
314
-
315
- # === API Configuration ===
316
- # Note: DRF base configuration is handled by django-revolution
317
- # These fields provide additional/extended settings on top of Revolution
318
- drf: Optional[DRFConfig] = Field(
319
- default=None,
320
- description="Extended Django REST Framework configuration (supplements Revolution)",
321
- )
322
-
323
- spectacular: Optional[SpectacularConfig] = Field(
324
- default=None,
325
- description="Extended DRF Spectacular configuration (supplements Revolution)",
326
- )
327
-
328
- # === Limits Configuration ===
329
- limits: Optional[LimitsConfig] = Field(
330
- default=None,
331
- description="Application limits configuration (file uploads, requests, etc.)",
332
- )
333
-
334
- # === API Keys Configuration ===
335
- api_keys: Optional[ApiKeys] = Field(
336
- default=None,
337
- description="API keys for external services (OpenAI, OpenRouter, etc.)",
338
- )
339
-
340
- # === Middleware Configuration ===
341
- custom_middleware: List[str] = Field(
342
- default_factory=list,
343
- description="Custom middleware classes (standard middleware added automatically)",
344
- )
345
-
346
- # === Internal State ===
347
- _base_dir: Optional[Path] = PrivateAttr(default=None)
348
- _django_settings: Optional[Dict[str, Any]] = PrivateAttr(default=None)
349
-
350
- def __init__(self, **data):
351
- """
352
- Initialize configuration with automatic setup.
353
-
354
- Performs the following setup steps:
355
- 1. Environment detection
356
- 2. Path resolution
357
- 3. Smart defaults application
358
- 4. Environment-specific configuration loading
359
- """
360
- super().__init__(**data)
361
-
362
- # Initialize internal state
363
- self._auto_detect_env_mode()
364
- self._resolve_paths()
365
- self._apply_smart_defaults()
366
- self._load_environment_config()
367
- self._validate_configuration()
368
-
369
- @field_validator("project_name")
370
- @classmethod
371
- def validate_project_name(cls, v: str) -> str:
372
- """Validate project name format."""
373
- if not v.replace(" ", "").replace("-", "").replace("_", "").isalnum():
374
- raise ValueError("Project name must contain only alphanumeric characters, " "spaces, hyphens, and underscores")
375
-
376
- return v
377
-
378
- @field_validator("secret_key")
379
- @classmethod
380
- def validate_secret_key(cls, v: str) -> str:
381
- """Validate Django SECRET_KEY."""
382
- if len(v) < 50:
383
- raise ValueError("SECRET_KEY must be at least 50 characters long")
384
-
385
- # Check for common insecure patterns
386
- insecure_patterns = [
387
- "django-insecure",
388
- "change-me",
389
- "your-secret-key",
390
- "dev-key",
391
- "test-key",
392
- ]
393
-
394
- v_lower = v.lower()
395
- for pattern in insecure_patterns:
396
- if pattern in v_lower:
397
- # This is a warning, not an error - allow for development
398
- break
399
-
400
- return v
401
-
402
- # validate_allowed_hosts removed - allowed_hosts now auto-generated from security_domains
403
-
404
- @field_validator("project_apps")
405
- @classmethod
406
- def validate_project_apps(cls, v: List[str]) -> List[str]:
407
- """Validate project apps list."""
408
- for app in v:
409
- if not app:
410
- raise ValueError("Empty app name in project_apps")
411
-
412
- # Basic app name validation
413
- if not app.replace(".", "").replace("_", "").isalnum():
414
- raise ValueError(f"Invalid app name '{app}': must contain only letters, numbers, dots, and underscores")
415
-
416
- return v
417
-
418
- @model_validator(mode="after")
419
- def validate_configuration_consistency(self) -> "DjangoConfig":
420
- """Validate overall configuration consistency."""
421
- # Ensure at least one database is configured
422
- if not self.databases:
423
- raise ConfigurationError("At least one database must be configured", suggestions=["Add a 'default' database to the databases field"])
424
-
425
- # Ensure 'default' database exists
426
- if "default" not in self.databases:
427
- raise ConfigurationError("'default' database is required", context={"available_databases": list(self.databases.keys())}, suggestions=["Add a database with alias 'default'"])
428
-
429
-
430
- # Validate database routing consistency - check migrate_to references
431
- referenced_databases = set()
432
- for alias, db_config in self.databases.items():
433
- if db_config.migrate_to:
434
- referenced_databases.add(db_config.migrate_to)
435
-
436
- missing_databases = referenced_databases - set(self.databases.keys())
437
- if missing_databases:
438
- raise ConfigurationError(f"Database routing references non-existent databases: {missing_databases}", context={"available_databases": list(self.databases.keys())}, suggestions=[f"Add database configurations for: {', '.join(missing_databases)}"])
439
-
440
- return self
441
-
442
- # === Environment Mode Properties ===
443
- @property
444
- def is_development(self) -> bool:
445
- """Check if running in development mode."""
446
- return self.env_mode == EnvironmentMode.DEVELOPMENT
447
-
448
- @property
449
- def is_production(self) -> bool:
450
- """Check if running in production mode."""
451
- return self.env_mode == EnvironmentMode.PRODUCTION
452
-
453
- @property
454
- def is_test(self) -> bool:
455
- """Check if running in test mode."""
456
- return self.env_mode == EnvironmentMode.TEST
457
-
458
- def _auto_detect_env_mode(self) -> None:
459
- """Auto-detect environment mode from various sources."""
460
- import os
461
-
462
- # Check environment variables first
463
- env_var = os.getenv("DJANGO_ENV", "").lower()
464
- if env_var in ["development", "dev"]:
465
- self.env_mode = EnvironmentMode.DEVELOPMENT
466
- elif env_var in ["production", "prod"]:
467
- self.env_mode = EnvironmentMode.PRODUCTION
468
- elif env_var in ["test", "testing"]:
469
- self.env_mode = EnvironmentMode.TEST
470
- elif hasattr(self, 'debug') and self.debug:
471
- # Auto-detect from debug flag if no env var set
472
- self.env_mode = EnvironmentMode.DEVELOPMENT
473
- # Otherwise keep the default (PRODUCTION)
474
-
475
- @property
476
- def base_dir(self) -> Path:
477
- """Get the base directory of the project."""
478
- if self._base_dir is None:
479
-
480
- # Start from current working directory
481
- current_path = Path(os.path.dirname(os.path.abspath(__file__)))
482
-
483
- # Look for manage.py in current directory and parents
484
- for path in [current_path] + list(current_path.parents):
485
- manage_py = path / "manage.py"
486
- if manage_py.exists() and manage_py.is_file():
487
- self._base_dir = path
488
- break
489
-
490
- # If still not found, use current directory
491
- if self._base_dir is None:
492
- self._base_dir = Path.cwd()
493
-
494
- return self._base_dir
495
-
496
- def _resolve_paths(self) -> None:
497
- """Resolve project paths and auto-detect missing configuration."""
498
- from django_cfg.utils.path_resolution import PathResolver
499
-
500
- try:
501
- # Find project root if not already set
502
- if self._base_dir is None:
503
- self._base_dir = PathResolver.find_project_root()
504
-
505
- # Auto-detect URL configuration if not set
506
- if not self.root_urlconf:
507
- detected_urlconf = PathResolver.detect_root_urlconf(self._base_dir)
508
- if detected_urlconf:
509
- self.root_urlconf = detected_urlconf
510
-
511
- # Auto-detect WSGI application if not set
512
- if not self.wsgi_application:
513
- detected_wsgi = PathResolver.detect_wsgi_application(self._base_dir)
514
- if detected_wsgi:
515
- self.wsgi_application = detected_wsgi
516
-
517
- except Exception as e:
518
- raise ConfigurationError(f"Failed to resolve project paths: {e}", suggestions=["Ensure manage.py exists in your project root", "Set root_urlconf and wsgi_application explicitly"]) from e
519
-
520
- def _apply_smart_defaults(self) -> None:
521
- """Apply environment-aware smart defaults."""
522
- from django_cfg.utils.smart_defaults import SmartDefaults
523
-
524
- try:
525
- # Apply cache defaults
526
- if self.cache_default:
527
- self.cache_default = SmartDefaults.configure_cache_backend(self.cache_default, self.env_mode, self.debug)
528
-
529
- if self.cache_sessions:
530
- self.cache_sessions = SmartDefaults.configure_cache_backend(self.cache_sessions, self.env_mode, self.debug)
531
-
532
- # Apply email defaults
533
- if self.email:
534
- self.email = SmartDefaults.configure_email_backend(self.email, self.env_mode, self.debug)
535
-
536
- except Exception as e:
537
- raise ConfigurationError(f"Failed to apply smart defaults: {e}", context={"environment": self.env_mode, "debug": self.debug}) from e
538
-
539
- def _load_environment_config(self) -> None:
540
- """Load environment-specific configuration from YAML files."""
541
- # TODO: Implement environment-specific configuration loading
542
- # This will be implemented when EnvironmentConfig model is created
543
- pass
544
-
545
- def _validate_configuration(self) -> None:
546
- """Perform final configuration validation."""
547
- from django_cfg.core.validation import ConfigurationValidator
548
-
549
- try:
550
- errors = ConfigurationValidator.validate(self)
551
- if errors:
552
- raise ValidationError(f"Configuration validation failed: {len(errors)} errors found", context={"errors": errors}, suggestions=["Fix the validation errors listed in context"])
553
- except Exception as e:
554
- if isinstance(e, ValidationError):
555
- raise
556
- raise ConfigurationError(f"Configuration validation failed: {e}") from e
557
-
558
- def get_all_settings(self) -> Dict[str, Any]:
559
- """
560
- Generate complete Django settings dictionary.
561
-
562
- Returns:
563
- Complete Django settings ready for use
564
-
565
- Raises:
566
- ConfigurationError: If settings generation fails
567
- """
568
- # Automatically set this config as the current global config
569
- set_current_config(self)
570
-
571
- if self._django_settings is None:
572
- from django_cfg.core.generation import SettingsGenerator
573
-
574
- try:
575
- self._django_settings = SettingsGenerator.generate(self)
576
- except Exception as e:
577
- raise ConfigurationError(f"Failed to generate Django settings: {e}", context={"config": self.model_dump(exclude={"_django_settings"})}) from e
578
-
579
- return self._django_settings
580
-
581
- def get_ticket_url(self, ticket_uuid: str) -> str:
582
- """
583
- Generate ticket URL using the configured template.
584
-
585
- Args:
586
- ticket_uuid: UUID of the support ticket
587
-
588
- Returns:
589
- Complete URL to the ticket
590
- """
591
- return self.ticket_url.format(
592
- site_url=self.site_url,
593
- uuid=ticket_uuid
594
- )
595
-
596
- def get_otp_url(self, otp_code: str) -> str:
597
- """
598
- Generate OTP verification URL using the configured template.
599
-
600
- Args:
601
- otp_code: OTP verification code
602
-
603
- Returns:
604
- Complete URL to the OTP verification page
605
- """
606
- return self.otp_url.format(
607
- site_url=self.site_url,
608
- code=otp_code
609
- )
610
-
611
- def should_enable_tasks(self) -> bool:
612
- """
613
- Determine if background tasks should be enabled.
614
-
615
- Tasks are enabled if:
616
- 1. Explicitly configured via tasks field
617
- 2. Knowledge base is enabled (requires background processing)
618
- 3. Agents are enabled (requires background processing)
619
-
620
- Returns:
621
- True if tasks should be enabled, False otherwise
622
- """
623
- # Check if explicitly configured
624
- if hasattr(self, 'tasks') and self.tasks and self.tasks.enabled:
625
- return True
626
-
627
- # Check if features that require tasks are enabled
628
- if self.enable_knowbase or self.enable_agents:
629
- return True
630
-
631
- # Check if agents module requires tasks
632
- if self.enable_agents:
633
- return True
634
-
635
- return False
636
-
637
- def get_enabled_apps(self) -> List[str]:
638
- """
639
- Get list of enabled django-cfg apps.
640
- """
641
-
642
- apps = [
643
- "django_cfg.apps.api.health",
644
- "django_cfg.apps.api.commands",
645
- ]
646
-
647
- if self.enable_support:
648
- apps.append("django_cfg.apps.support")
649
- if self.enable_accounts:
650
- apps.append("django_cfg.apps.accounts")
651
- if self.enable_newsletter:
652
- apps.append("django_cfg.apps.newsletter")
653
- if self.enable_leads:
654
- apps.append("django_cfg.apps.leads")
655
- if self.enable_knowbase:
656
- apps.append("django_cfg.apps.knowbase")
657
- if self.enable_agents:
658
- apps.append("django_cfg.apps.agents")
659
- if self.enable_maintenance:
660
- apps.append("django_cfg.apps.maintenance")
661
- if self.payments and self.payments.enabled:
662
- apps.append("django_cfg.apps.payments")
663
- return apps
664
-
665
- def get_installed_apps(self) -> List[str]:
666
- """
667
- Get complete list of installed Django apps.
668
-
669
- Returns:
670
- List of Django app names
671
- """
672
- # Start with DEFAULT_APPS but handle accounts specially
673
- apps = []
674
-
675
- # Add apps before admin
676
- for app in DEFAULT_APPS:
677
- if app == "django.contrib.admin":
678
- # Insert accounts before admin if enabled (for proper migration order)
679
- if self.enable_accounts:
680
- apps.append("django_cfg.apps.accounts")
681
- apps.append(app)
682
-
683
- # Add other django-cfg built-in apps after standard apps
684
- if self.enable_support:
685
- apps.append("django_cfg.apps.support")
686
- if self.enable_newsletter:
687
- apps.append("django_cfg.apps.newsletter")
688
- if self.enable_leads:
689
- apps.append("django_cfg.apps.leads")
690
- if self.enable_knowbase:
691
- apps.append("django_cfg.apps.knowbase")
692
- if self.enable_agents:
693
- apps.append("django_cfg.apps.agents")
694
- if self.enable_maintenance:
695
- apps.append("django_cfg.apps.maintenance")
696
- if self.payments and self.payments.enabled:
697
- apps.append("django_cfg.apps.payments")
698
-
699
- # Auto-enable tasks if needed
700
- if self.should_enable_tasks():
701
- apps.append("django_dramatiq") # Add django_dramatiq first
702
- apps.append("django_cfg.apps.tasks")
703
-
704
- # Auto-detect dashboard apps from Unfold callback
705
- dashboard_apps = self._get_dashboard_apps_from_callback()
706
- apps.extend(dashboard_apps)
707
-
708
- # Add project-specific apps
709
- apps.extend(self.project_apps)
710
-
711
- # Remove duplicates while preserving order
712
- seen = set()
713
- apps = [app for app in apps if not (app in seen or seen.add(app))]
714
-
715
- return apps
716
-
717
- def _get_dashboard_apps_from_callback(self) -> List[str]:
718
- """
719
- Auto-detect dashboard apps from Unfold dashboard_callback setting.
720
-
721
- Extracts app names from callback paths like:
722
- - "api.dashboard.callbacks.main_dashboard_callback" -> ["api.dashboard"]
723
- - "myproject.admin.callbacks.dashboard" -> ["myproject.admin"]
724
-
725
- Returns:
726
- List of dashboard app names to add to INSTALLED_APPS
727
- """
728
- dashboard_apps = []
729
-
730
- if not self.unfold or not self.unfold.theme:
731
- return dashboard_apps
732
-
733
- callback_path = getattr(self.unfold.theme, "dashboard_callback", None)
734
- if not callback_path:
735
- return dashboard_apps
736
-
737
- try:
738
- # Parse callback path: "api.dashboard.callbacks.main_dashboard_callback"
739
- # Extract app part: "api.dashboard"
740
- parts = callback_path.split(".")
741
-
742
- # Look for common callback patterns
743
- callback_indicators = ["callbacks", "views", "handlers"]
744
-
745
- # Find the callback indicator and extract app path before it
746
- app_parts = []
747
- for i, part in enumerate(parts):
748
- if part in callback_indicators:
749
- app_parts = parts[:i] # Everything before the callback indicator
750
- break
751
-
752
- # If no callback indicator found, assume last part is function name
753
- if not app_parts and len(parts) > 1:
754
- app_parts = parts[:-1] # Everything except the last part
755
-
756
- if app_parts:
757
- app_name = ".".join(app_parts)
758
- dashboard_apps.append(app_name)
759
-
760
- except Exception:
761
- # If parsing fails, silently continue - dashboard callback is optional
762
- pass
763
-
764
- return dashboard_apps
765
-
766
- def get_middleware(self) -> List[str]:
767
- """
768
- Get complete middleware stack.
769
-
770
- Returns:
771
- List of middleware class paths
772
- """
773
- # Standard Django middleware (always included)
774
- middleware = [
775
- "django.middleware.security.SecurityMiddleware",
776
- "whitenoise.middleware.WhiteNoiseMiddleware", # Add WhiteNoise for static files
777
- "django.contrib.sessions.middleware.SessionMiddleware",
778
- "django.middleware.common.CommonMiddleware",
779
- "django.middleware.csrf.CsrfViewMiddleware",
780
- "django.contrib.auth.middleware.AuthenticationMiddleware",
781
- "django.contrib.messages.middleware.MessageMiddleware",
782
- "django.middleware.clickjacking.XFrameOptionsMiddleware",
783
- ]
784
-
785
- # Add CORS middleware if security domains are configured
786
- if self.security_domains:
787
- middleware.insert(2, "corsheaders.middleware.CorsMiddleware") # Insert after WhiteNoise
788
-
789
- # Add Django CFG middleware based on enabled features
790
- if self.enable_accounts:
791
- middleware.append("django_cfg.middleware.UserActivityMiddleware")
792
-
793
- # Add payments middleware if enabled
794
- if self.payments and self.payments.enabled:
795
- middleware.extend(self.payments.get_middleware_classes())
796
-
797
- # Add custom middleware
798
- middleware.extend(self.custom_middleware)
799
-
800
- return middleware
801
-
802
- def get_allowed_hosts(self) -> List[str]:
803
- """
804
- Generate ALLOWED_HOSTS from security_domains.
805
-
806
- Returns:
807
- List of allowed hosts including localhost for development
808
- """
809
- allowed_hosts = []
810
-
811
- # Add security domains if configured
812
- if self.security_domains:
813
-
814
- for domain in self.security_domains:
815
- # Parse URL properly
816
- if "://" in domain:
817
- # Use urlparse to extract hostname correctly
818
- parsed_url = urlparse(domain)
819
- hostname = parsed_url.netloc.split(":")[0] # Remove port if present
820
- else:
821
- hostname = domain
822
-
823
- # Add hostname itself
824
- if hostname not in allowed_hosts:
825
- allowed_hosts.append(hostname)
826
-
827
- # Add www subdomain if not already a subdomain and not localhost
828
- if not hostname.startswith("www.") and not hostname.startswith("*.") and not hostname.startswith("localhost") and not hostname.startswith("127.0.0.1"):
829
- www_hostname = f"www.{hostname}"
830
- if www_hostname not in allowed_hosts:
831
- allowed_hosts.append(www_hostname)
832
-
833
- # Always allow localhost and 127.0.0.1 for development
834
- localhost_hosts = ["localhost", "127.0.0.1", "0.0.0.0"]
835
- for host in localhost_hosts:
836
- if host not in allowed_hosts:
837
- allowed_hosts.append(host)
838
-
839
- # If no domains configured, allow all (development mode)
840
- if not self.security_domains:
841
- allowed_hosts = ["*"]
842
-
843
- return allowed_hosts
844
-
845
- def get_site_url(self, path: str = "") -> str:
846
- """
847
- Get the site URL with optional path.
848
-
849
- Args:
850
- path: Optional path to append to site URL
851
-
852
- Returns:
853
- Complete URL with path
854
- """
855
- if path:
856
- path = path.lstrip("/")
857
- return f"{self.site_url.rstrip('/')}/{path}"
858
- return self.site_url
859
-
860
-
861
- def invalidate_cache(self) -> None:
862
- """Invalidate cached Django settings to force regeneration."""
863
- self._django_settings = None
864
-
865
- def model_dump_for_django(self) -> Dict[str, Any]:
866
- """
867
- Dump model data in format suitable for Django settings.
868
-
869
- Returns:
870
- Model data with internal fields excluded
871
- """
872
- return self.model_dump(exclude={"_base_dir", "_django_settings"}, exclude_none=True)
873
-
874
-
875
- # Global config instance for access from other modules
876
- _current_config = None
877
-
878
- def get_current_config():
879
- """
880
- Get the current DjangoConfig instance.
881
-
882
- Returns:
883
- The current DjangoConfig instance or None if not set
884
- """
885
- global _current_config
886
- return _current_config
887
-
888
- def set_current_config(config: DjangoConfig):
889
- """
890
- Set the current DjangoConfig instance.
891
-
892
- Args:
893
- config: The DjangoConfig instance to set as current
894
- """
895
- global _current_config
896
- _current_config = config
897
16
 
898
- # Export the main class
17
+ # Public API
899
18
  __all__ = [
19
+ # Main config
900
20
  "DjangoConfig",
21
+ # Enums
22
+ "EnvironmentMode",
23
+ "StartupInfoMode",
24
+ # Constants
25
+ "DEFAULT_APPS",
26
+ "DEFAULT_MIDDLEWARE",
27
+ # Global state
901
28
  "get_current_config",
902
29
  "set_current_config",
30
+ "clear_current_config",
903
31
  ]