django-cfg 1.3.13__py3-none-any.whl → 1.4.3__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 (446) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/apps/accounts/admin/user_admin.py +39 -16
  3. django_cfg/apps/accounts/serializers/profile.py +1 -1
  4. django_cfg/apps/accounts/services/otp_service.py +18 -11
  5. django_cfg/apps/accounts/signals.py +15 -24
  6. django_cfg/apps/accounts/utils/notifications.py +217 -358
  7. django_cfg/apps/accounts/views/otp.py +2 -2
  8. django_cfg/apps/accounts/views/webhook.py +1 -1
  9. django_cfg/apps/agents/core/django_agent.py +1 -1
  10. django_cfg/apps/agents/examples/__init__.py +3 -0
  11. django_cfg/apps/agents/examples/simple_example.py +161 -0
  12. django_cfg/apps/api/commands/views.py +66 -83
  13. django_cfg/apps/api/health/drf_views.py +269 -0
  14. django_cfg/apps/api/health/serializers.py +45 -0
  15. django_cfg/apps/api/health/urls.py +6 -1
  16. django_cfg/apps/knowbase/admin/actions/__init__.py +13 -0
  17. django_cfg/apps/knowbase/admin/actions/visibility_actions.py +56 -0
  18. django_cfg/apps/knowbase/admin/document_admin.py +136 -270
  19. django_cfg/apps/knowbase/admin/helpers/__init__.py +17 -0
  20. django_cfg/apps/knowbase/admin/helpers/configs.py +72 -0
  21. django_cfg/apps/knowbase/admin/helpers/display_helpers.py +156 -0
  22. django_cfg/apps/knowbase/admin/helpers/statistics.py +108 -0
  23. django_cfg/apps/knowbase/config/constance_fields.py +1 -1
  24. django_cfg/apps/knowbase/config/settings.py +2 -2
  25. django_cfg/apps/knowbase/examples/__init__.py +3 -0
  26. django_cfg/apps/knowbase/examples/external_data_usage.py +191 -0
  27. django_cfg/apps/knowbase/mixins/__init__.py +19 -2
  28. django_cfg/apps/knowbase/mixins/config/__init__.py +14 -0
  29. django_cfg/apps/knowbase/mixins/config/defaults.py +75 -0
  30. django_cfg/apps/knowbase/mixins/config/meta_config.py +120 -0
  31. django_cfg/apps/knowbase/mixins/creator.py +10 -10
  32. django_cfg/apps/knowbase/mixins/examples/vehicle_model_example.py +199 -0
  33. django_cfg/apps/knowbase/mixins/external_data_mixin.py +105 -403
  34. django_cfg/apps/knowbase/mixins/generators/__init__.py +16 -0
  35. django_cfg/apps/knowbase/mixins/generators/content_generator.py +218 -0
  36. django_cfg/apps/knowbase/mixins/generators/field_analyzer.py +76 -0
  37. django_cfg/apps/knowbase/mixins/generators/metadata_generator.py +124 -0
  38. django_cfg/apps/knowbase/mixins/service.py +2 -2
  39. django_cfg/apps/knowbase/services/archive/__init__.py +1 -0
  40. django_cfg/apps/knowbase/services/archive/analyzers/__init__.py +17 -0
  41. django_cfg/apps/knowbase/services/archive/analyzers/complexity_analyzer.py +33 -0
  42. django_cfg/apps/knowbase/services/archive/analyzers/purpose_detector.py +36 -0
  43. django_cfg/apps/knowbase/services/archive/analyzers/quality_analyzer.py +39 -0
  44. django_cfg/apps/knowbase/services/archive/analyzers/tag_generator.py +103 -0
  45. django_cfg/apps/knowbase/services/archive/chunking/__init__.py +19 -0
  46. django_cfg/apps/knowbase/services/archive/chunking/base.py +81 -0
  47. django_cfg/apps/knowbase/services/archive/chunking/json_chunker.py +62 -0
  48. django_cfg/apps/knowbase/services/archive/chunking/markdown_chunker.py +107 -0
  49. django_cfg/apps/knowbase/services/archive/chunking/python_chunker.py +248 -0
  50. django_cfg/apps/knowbase/services/archive/chunking/text_chunker.py +70 -0
  51. django_cfg/apps/knowbase/services/archive/chunking_service.py +110 -729
  52. django_cfg/apps/knowbase/services/archive/context/__init__.py +14 -0
  53. django_cfg/apps/knowbase/services/archive/context/builders.py +220 -0
  54. django_cfg/apps/knowbase/services/archive/context/models.py +38 -0
  55. django_cfg/apps/knowbase/services/embedding/models.py +18 -14
  56. django_cfg/apps/knowbase/services/embedding/processors.py +6 -3
  57. django_cfg/apps/knowbase/tasks/document_processing.py +11 -3
  58. django_cfg/apps/leads/tests.py +1 -1
  59. django_cfg/apps/payments/admin/api_keys_admin.py +1 -1
  60. django_cfg/apps/payments/admin/balance_admin.py +1 -1
  61. django_cfg/apps/payments/admin/currencies_admin.py +1 -1
  62. django_cfg/apps/payments/admin/payments_admin.py +1 -1
  63. django_cfg/apps/payments/admin/subscriptions_admin.py +1 -1
  64. django_cfg/apps/payments/admin_interface/templates/payments/base.html +59 -126
  65. django_cfg/apps/payments/admin_interface/views/api/payments.py +1 -1
  66. django_cfg/apps/payments/admin_interface/views/api/stats.py +1 -1
  67. django_cfg/apps/payments/admin_interface/views/api/users.py +1 -1
  68. django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +1 -1
  69. django_cfg/apps/payments/admin_interface/views/api/webhook_public.py +1 -1
  70. django_cfg/apps/payments/admin_interface/views/base.py +29 -2
  71. django_cfg/apps/payments/apps.py +1 -1
  72. django_cfg/apps/payments/config/django_cfg_integration.py +2 -2
  73. django_cfg/apps/payments/config/helpers.py +3 -2
  74. django_cfg/apps/payments/management/commands/cleanup_expired_data.py +1 -1
  75. django_cfg/apps/payments/management/commands/currency_stats.py +1 -1
  76. django_cfg/apps/payments/management/commands/manage_currencies.py +1 -1
  77. django_cfg/apps/payments/management/commands/manage_providers.py +1 -1
  78. django_cfg/apps/payments/management/commands/process_pending_payments.py +1 -1
  79. django_cfg/apps/payments/management/commands/test_providers.py +1 -1
  80. django_cfg/apps/payments/middleware/api_access.py +1 -1
  81. django_cfg/apps/payments/middleware/rate_limiting.py +1 -1
  82. django_cfg/apps/payments/middleware/usage_tracking.py +1 -1
  83. django_cfg/apps/payments/models/balance.py +2 -2
  84. django_cfg/apps/payments/models/managers/api_key_managers.py +1 -1
  85. django_cfg/apps/payments/models/managers/balance_managers.py +1 -1
  86. django_cfg/apps/payments/models/managers/currency_managers.py +1 -1
  87. django_cfg/apps/payments/models/managers/payment_managers.py +1 -1
  88. django_cfg/apps/payments/models/managers/subscription_managers.py +1 -1
  89. django_cfg/apps/payments/models/payments.py +2 -2
  90. django_cfg/apps/payments/services/cache_service/__init__.py +1 -1
  91. django_cfg/apps/payments/services/cache_service/simple_cache.py +10 -5
  92. django_cfg/apps/payments/services/core/base.py +1 -1
  93. django_cfg/apps/payments/services/core/currency/__init__.py +13 -0
  94. django_cfg/apps/payments/services/core/currency/currency_converter.py +57 -0
  95. django_cfg/apps/payments/services/core/currency/currency_validator.py +61 -0
  96. django_cfg/apps/payments/services/core/operations/__init__.py +15 -0
  97. django_cfg/apps/payments/services/core/operations/payment_canceller.py +100 -0
  98. django_cfg/apps/payments/services/core/operations/payment_creator.py +196 -0
  99. django_cfg/apps/payments/services/core/operations/status_checker.py +100 -0
  100. django_cfg/apps/payments/services/core/payment_service.py +124 -612
  101. django_cfg/apps/payments/services/core/providers/__init__.py +13 -0
  102. django_cfg/apps/payments/services/core/providers/provider_client.py +132 -0
  103. django_cfg/apps/payments/services/core/providers/status_mapper.py +89 -0
  104. django_cfg/apps/payments/services/core/utils/__init__.py +13 -0
  105. django_cfg/apps/payments/services/core/utils/data_converter.py +48 -0
  106. django_cfg/apps/payments/services/core/utils/statistics_calculator.py +69 -0
  107. django_cfg/apps/payments/services/providers/base.py +1 -1
  108. django_cfg/apps/payments/services/providers/nowpayments/__init__.py +3 -3
  109. django_cfg/apps/payments/services/providers/nowpayments/parsers/__init__.py +9 -0
  110. django_cfg/apps/payments/services/providers/nowpayments/parsers/data/__init__.py +23 -0
  111. django_cfg/apps/payments/services/providers/nowpayments/parsers/data/constants.py +23 -0
  112. django_cfg/apps/payments/services/providers/nowpayments/parsers/data/currency_names.py +244 -0
  113. django_cfg/apps/payments/services/providers/nowpayments/parsers/data/patterns.py +511 -0
  114. django_cfg/apps/payments/services/providers/nowpayments/parsers/parser.py +168 -0
  115. django_cfg/apps/payments/services/providers/nowpayments/provider.py +1 -1
  116. django_cfg/apps/payments/services/providers/nowpayments/sync.py +1 -1
  117. django_cfg/apps/payments/services/providers/registry.py +1 -1
  118. django_cfg/apps/payments/services/providers/sync_service.py +1 -1
  119. django_cfg/apps/payments/signals/__init__.py +1 -1
  120. django_cfg/apps/payments/signals/api_key_signals.py +1 -1
  121. django_cfg/apps/payments/signals/balance_signals.py +1 -1
  122. django_cfg/apps/payments/signals/payment_signals.py +1 -1
  123. django_cfg/apps/payments/signals/subscription_signals.py +1 -1
  124. django_cfg/apps/payments/views/api/api_keys.py +1 -1
  125. django_cfg/apps/payments/views/api/balances.py +1 -1
  126. django_cfg/apps/payments/views/api/base.py +1 -1
  127. django_cfg/apps/payments/views/api/currencies.py +1 -1
  128. django_cfg/apps/payments/views/api/payments.py +1 -1
  129. django_cfg/apps/payments/views/api/subscriptions.py +1 -1
  130. django_cfg/apps/payments/views/api/webhooks.py +1 -1
  131. django_cfg/apps/payments/views/serializers/api_keys.py +1 -1
  132. django_cfg/apps/payments/views/serializers/balances.py +1 -1
  133. django_cfg/apps/payments/views/serializers/currencies.py +1 -1
  134. django_cfg/apps/payments/views/serializers/payments.py +1 -1
  135. django_cfg/apps/payments/views/serializers/subscriptions.py +1 -1
  136. django_cfg/apps/payments/views/serializers/webhooks.py +1 -1
  137. django_cfg/apps/support/admin/support_admin.py +21 -13
  138. django_cfg/apps/support/templates/support/chat/access_denied.html +21 -27
  139. django_cfg/apps/support/templates/support/chat/ticket_chat.html +183 -254
  140. django_cfg/apps/support/utils/support_email_service.py +1 -1
  141. django_cfg/apps/tasks/templates/tasks/layout/base.html +20 -115
  142. django_cfg/apps/tasks/utils/simulator.py +1 -1
  143. django_cfg/apps/tasks/views/dashboard.py +33 -3
  144. django_cfg/apps/urls.py +5 -1
  145. django_cfg/cli/README.md +57 -471
  146. django_cfg/cli/commands/create_project.py +140 -529
  147. django_cfg/cli/main.py +13 -10
  148. django_cfg/core/__init__.py +63 -6
  149. django_cfg/core/base/__init__.py +5 -0
  150. django_cfg/core/base/config_model.py +652 -0
  151. django_cfg/core/builders/__init__.py +11 -0
  152. django_cfg/core/builders/apps_builder.py +258 -0
  153. django_cfg/core/builders/middleware_builder.py +115 -0
  154. django_cfg/core/builders/security_builder.py +96 -0
  155. django_cfg/core/config.py +20 -892
  156. django_cfg/core/constants.py +69 -0
  157. django_cfg/core/environment/__init__.py +9 -0
  158. django_cfg/core/exceptions.py +45 -298
  159. django_cfg/core/generation/__init__.py +51 -0
  160. django_cfg/core/generation/core_generators/__init__.py +0 -0
  161. django_cfg/core/generation/core_generators/settings.py +90 -0
  162. django_cfg/core/generation/core_generators/static.py +82 -0
  163. django_cfg/core/generation/core_generators/templates.py +141 -0
  164. django_cfg/core/generation/data_generators/__init__.py +15 -0
  165. django_cfg/core/generation/data_generators/cache.py +132 -0
  166. django_cfg/core/generation/data_generators/database.py +117 -0
  167. django_cfg/core/generation/generation.py +92 -0
  168. django_cfg/core/generation/integration_generators/__init__.py +21 -0
  169. django_cfg/core/generation/integration_generators/api.py +237 -0
  170. django_cfg/core/generation/integration_generators/sessions.py +65 -0
  171. django_cfg/core/generation/integration_generators/tailwind.py +54 -0
  172. django_cfg/core/generation/integration_generators/tasks.py +92 -0
  173. django_cfg/core/generation/integration_generators/third_party.py +144 -0
  174. django_cfg/core/generation/orchestrator.py +285 -0
  175. django_cfg/core/generation/protocols.py +30 -0
  176. django_cfg/core/generation/security_generators/__init__.py +0 -0
  177. django_cfg/core/generation/utility_generators/__init__.py +24 -0
  178. django_cfg/core/generation/utility_generators/email.py +58 -0
  179. django_cfg/core/generation/utility_generators/i18n.py +66 -0
  180. django_cfg/core/generation/utility_generators/limits.py +58 -0
  181. django_cfg/core/generation/utility_generators/logging.py +66 -0
  182. django_cfg/core/generation/utility_generators/security.py +101 -0
  183. django_cfg/core/generation/utils/__init__.py +0 -0
  184. django_cfg/core/generation/utils/helpers.py +32 -0
  185. django_cfg/core/integration/__init__.py +18 -25
  186. django_cfg/core/integration/display/startup.py +146 -133
  187. django_cfg/core/integration/url_integration.py +13 -2
  188. django_cfg/core/services/__init__.py +5 -0
  189. django_cfg/core/services/config_service.py +121 -0
  190. django_cfg/core/state/__init__.py +9 -0
  191. django_cfg/core/state/registry.py +84 -0
  192. django_cfg/core/types/__init__.py +15 -0
  193. django_cfg/core/types/aliases.py +15 -0
  194. django_cfg/core/types/enums.py +49 -0
  195. django_cfg/dashboard/DEBUG_README.md +105 -0
  196. django_cfg/dashboard/REFACTORING_SUMMARY.md +237 -0
  197. django_cfg/dashboard/__init__.py +24 -0
  198. django_cfg/dashboard/components.py +308 -0
  199. django_cfg/dashboard/debug.py +176 -0
  200. django_cfg/dashboard/management/__init__.py +0 -0
  201. django_cfg/dashboard/management/commands/__init__.py +0 -0
  202. django_cfg/dashboard/management/commands/debug_dashboard.py +109 -0
  203. django_cfg/dashboard/sections/__init__.py +1 -0
  204. django_cfg/dashboard/sections/base.py +128 -0
  205. django_cfg/dashboard/sections/commands.py +32 -0
  206. django_cfg/dashboard/sections/overview.py +394 -0
  207. django_cfg/dashboard/sections/stats.py +48 -0
  208. django_cfg/dashboard/sections/system.py +73 -0
  209. django_cfg/management/commands/check_settings.py +6 -2
  210. django_cfg/management/commands/clear_constance.py +6 -1
  211. django_cfg/management/commands/create_token.py +5 -4
  212. django_cfg/management/commands/generate.py +5 -0
  213. django_cfg/management/commands/list_urls.py +7 -2
  214. django_cfg/management/commands/migrate_all.py +6 -2
  215. django_cfg/management/commands/migrator.py +6 -1
  216. django_cfg/management/commands/rundramatiq.py +6 -1
  217. django_cfg/management/commands/rundramatiq_simulator.py +11 -4
  218. django_cfg/management/commands/runserver_ngrok.py +9 -7
  219. django_cfg/management/commands/script.py +25 -21
  220. django_cfg/management/commands/show_config.py +6 -1
  221. django_cfg/management/commands/show_urls.py +8 -3
  222. django_cfg/management/commands/superuser.py +5 -4
  223. django_cfg/management/commands/task_clear.py +8 -3
  224. django_cfg/management/commands/task_status.py +8 -3
  225. django_cfg/management/commands/test_email.py +6 -1
  226. django_cfg/management/commands/test_telegram.py +6 -1
  227. django_cfg/management/commands/test_twilio.py +6 -1
  228. django_cfg/management/commands/tree.py +7 -4
  229. django_cfg/models/__init__.py +88 -3
  230. django_cfg/models/api/__init__.py +27 -0
  231. django_cfg/models/{api.py → api/config.py} +1 -1
  232. django_cfg/models/api/drf/__init__.py +21 -0
  233. django_cfg/models/api/drf/config.py +101 -0
  234. django_cfg/models/api/drf/redoc.py +31 -0
  235. django_cfg/models/api/drf/spectacular.py +129 -0
  236. django_cfg/models/api/drf/swagger.py +59 -0
  237. django_cfg/models/{api_keys.py → api/keys.py} +16 -6
  238. django_cfg/models/{limits.py → api/limits.py} +0 -1
  239. django_cfg/models/base/__init__.py +14 -0
  240. django_cfg/models/django/__init__.py +16 -0
  241. django_cfg/models/{constance.py → django/constance.py} +1 -1
  242. django_cfg/models/{environment.py → django/environment.py} +1 -1
  243. django_cfg/models/infrastructure/__init__.py +17 -0
  244. django_cfg/models/{cache.py → infrastructure/cache.py} +3 -2
  245. django_cfg/models/infrastructure/database/__init__.py +22 -0
  246. django_cfg/models/infrastructure/database/config.py +265 -0
  247. django_cfg/models/infrastructure/database/converters.py +91 -0
  248. django_cfg/models/infrastructure/database/parsers.py +96 -0
  249. django_cfg/models/infrastructure/database/routing.py +85 -0
  250. django_cfg/models/infrastructure/database/validators.py +170 -0
  251. django_cfg/models/{logging.py → infrastructure/logging.py} +1 -1
  252. django_cfg/models/{security.py → infrastructure/security.py} +2 -2
  253. django_cfg/models/ngrok/__init__.py +11 -0
  254. django_cfg/models/ngrok/auth.py +37 -0
  255. django_cfg/models/ngrok/config.py +77 -0
  256. django_cfg/models/ngrok/tunnel.py +35 -0
  257. django_cfg/models/payments/__init__.py +20 -0
  258. django_cfg/models/payments/api_keys.py +57 -0
  259. django_cfg/models/{payments.py → payments/config.py} +56 -154
  260. django_cfg/models/payments/providers/__init__.py +15 -0
  261. django_cfg/models/payments/providers/base.py +25 -0
  262. django_cfg/models/payments/providers/nowpayments.py +48 -0
  263. django_cfg/models/services/__init__.py +18 -0
  264. django_cfg/models/services/base.py +65 -0
  265. django_cfg/models/{email.py → services/email.py} +1 -1
  266. django_cfg/models/services/telegram.py +172 -0
  267. django_cfg/models/tasks/__init__.py +51 -0
  268. django_cfg/models/tasks/backends.py +250 -0
  269. django_cfg/models/tasks/config.py +314 -0
  270. django_cfg/models/tasks/utils.py +174 -0
  271. django_cfg/modules/base.py +18 -3
  272. django_cfg/modules/django_admin/decorators/actions.py +1 -1
  273. django_cfg/modules/django_admin/decorators/display.py +1 -1
  274. django_cfg/modules/django_admin/mixins/standalone_actions_mixin.py +1 -1
  275. django_cfg/modules/django_currency/examples/__init__.py +3 -0
  276. django_cfg/modules/django_currency/examples/example_database_usage.py +144 -0
  277. django_cfg/modules/django_drf_theme/CHANGELOG.md +210 -0
  278. django_cfg/modules/django_drf_theme/EXAMPLE.md +465 -0
  279. django_cfg/modules/django_drf_theme/IMPLEMENTATION.md +232 -0
  280. django_cfg/modules/django_drf_theme/README.md +207 -0
  281. django_cfg/modules/django_drf_theme/TAILWIND_CDN_GUIDE.md +274 -0
  282. django_cfg/modules/django_drf_theme/__init__.py +23 -0
  283. django_cfg/modules/django_drf_theme/apps.py +15 -0
  284. django_cfg/modules/django_drf_theme/renderers.py +58 -0
  285. django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/api.html +375 -0
  286. django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/base.html +938 -0
  287. django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/forms/filter_form.html +132 -0
  288. django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/forms/raw_data_form.html +123 -0
  289. django_cfg/modules/django_drf_theme/templatetags/__init__.py +1 -0
  290. django_cfg/modules/django_drf_theme/templatetags/tailwind_tags.py +57 -0
  291. django_cfg/modules/django_email/__init__.py +14 -0
  292. django_cfg/modules/{django_email.py → django_email/service.py} +78 -113
  293. django_cfg/modules/django_email/utils.py +40 -0
  294. django_cfg/modules/django_health/__init__.py +9 -0
  295. django_cfg/modules/{django_health.py → django_health/service.py} +23 -21
  296. django_cfg/modules/django_ipc_client/README.md +346 -0
  297. django_cfg/modules/django_ipc_client/__init__.py +51 -0
  298. django_cfg/modules/django_ipc_client/client.py +540 -0
  299. django_cfg/modules/django_ipc_client/config.py +207 -0
  300. django_cfg/modules/django_ipc_client/dashboard/README.md +517 -0
  301. django_cfg/modules/django_ipc_client/dashboard/UNFOLD_INTEGRATION.md +439 -0
  302. django_cfg/modules/django_ipc_client/dashboard/__init__.py +11 -0
  303. django_cfg/modules/django_ipc_client/dashboard/apps.py +22 -0
  304. django_cfg/modules/django_ipc_client/dashboard/monitor.py +435 -0
  305. django_cfg/modules/django_ipc_client/dashboard/static/django_ipc_dashboard/js/dashboard.js +373 -0
  306. django_cfg/modules/django_ipc_client/dashboard/templates/django_ipc_dashboard/base.html +76 -0
  307. django_cfg/modules/django_ipc_client/dashboard/templates/django_ipc_dashboard/dashboard.html +200 -0
  308. django_cfg/modules/django_ipc_client/dashboard/urls.py +22 -0
  309. django_cfg/modules/django_ipc_client/dashboard/urls_admin.py +9 -0
  310. django_cfg/modules/django_ipc_client/dashboard/views.py +251 -0
  311. django_cfg/modules/django_ipc_client/exceptions.py +201 -0
  312. django_cfg/modules/django_llm/llm/client.py +155 -550
  313. django_cfg/modules/django_llm/llm/embeddings/__init__.py +13 -0
  314. django_cfg/modules/django_llm/llm/embeddings/mock_embedder.py +106 -0
  315. django_cfg/modules/django_llm/llm/embeddings/openai_embedder.py +79 -0
  316. django_cfg/modules/django_llm/llm/models_api/__init__.py +9 -0
  317. django_cfg/modules/django_llm/llm/models_api/models_query.py +163 -0
  318. django_cfg/modules/django_llm/llm/providers/__init__.py +15 -0
  319. django_cfg/modules/django_llm/llm/providers/config_builder.py +103 -0
  320. django_cfg/modules/django_llm/llm/providers/provider_manager.py +148 -0
  321. django_cfg/modules/django_llm/llm/providers/provider_selector.py +60 -0
  322. django_cfg/modules/django_llm/llm/requests/__init__.py +15 -0
  323. django_cfg/modules/django_llm/llm/requests/cache_manager.py +170 -0
  324. django_cfg/modules/django_llm/llm/requests/chat_handler.py +199 -0
  325. django_cfg/modules/django_llm/llm/requests/embedding_handler.py +113 -0
  326. django_cfg/modules/django_llm/llm/responses/__init__.py +9 -0
  327. django_cfg/modules/django_llm/llm/responses/response_builder.py +131 -0
  328. django_cfg/modules/django_llm/llm/stats/__init__.py +9 -0
  329. django_cfg/modules/django_llm/llm/stats/stats_manager.py +107 -0
  330. django_cfg/modules/django_llm/translator/detectors/__init__.py +13 -0
  331. django_cfg/modules/django_llm/translator/detectors/language_detector.py +90 -0
  332. django_cfg/modules/django_llm/translator/detectors/script_detector.py +153 -0
  333. django_cfg/modules/django_llm/translator/stats/__init__.py +11 -0
  334. django_cfg/modules/django_llm/translator/stats/stats_tracker.py +85 -0
  335. django_cfg/modules/django_llm/translator/translator.py +150 -603
  336. django_cfg/modules/django_llm/translator/translators/__init__.py +15 -0
  337. django_cfg/modules/django_llm/translator/translators/json_translator.py +316 -0
  338. django_cfg/modules/django_llm/translator/translators/text_translator.py +139 -0
  339. django_cfg/modules/django_llm/translator/utils/__init__.py +13 -0
  340. django_cfg/modules/django_llm/translator/utils/prompt_builder.py +110 -0
  341. django_cfg/modules/django_llm/translator/utils/text_utils.py +114 -0
  342. django_cfg/modules/django_logging/FIXES_SUMMARY.md +276 -0
  343. django_cfg/modules/django_logging/LOGGING_GUIDE.md +504 -0
  344. django_cfg/modules/django_logging/__init__.py +14 -0
  345. django_cfg/modules/{django_logger.py → django_logging/django_logger.py} +13 -13
  346. django_cfg/modules/{logger.py → django_logging/logger.py} +14 -4
  347. django_cfg/modules/django_ngrok/__init__.py +39 -0
  348. django_cfg/modules/{django_ngrok.py → django_ngrok/service.py} +14 -42
  349. django_cfg/modules/django_rpc_old/POETRY.md +344 -0
  350. django_cfg/modules/django_rpc_old/README.md +397 -0
  351. django_cfg/modules/django_rpc_old/TESTING.md +358 -0
  352. django_cfg/modules/django_rpc_old/__init__.py +39 -0
  353. django_cfg/modules/django_rpc_old/client.py +531 -0
  354. django_cfg/modules/django_rpc_old/config.py +279 -0
  355. django_cfg/modules/django_rpc_old/exceptions.py +172 -0
  356. django_cfg/modules/django_tailwind/README.md +478 -0
  357. django_cfg/modules/django_tailwind/__init__.py +7 -0
  358. django_cfg/modules/django_tailwind/apps.py +10 -0
  359. django_cfg/modules/django_tailwind/templates/django_tailwind/app.html +5 -0
  360. django_cfg/modules/django_tailwind/templates/django_tailwind/base.html +117 -0
  361. django_cfg/modules/django_tailwind/templates/django_tailwind/components/navbar.html +124 -0
  362. django_cfg/modules/django_tailwind/templates/django_tailwind/components/theme_toggle.html +54 -0
  363. django_cfg/modules/django_tailwind/templates/django_tailwind/components/user_menu.html +116 -0
  364. django_cfg/modules/django_tailwind/templates/django_tailwind/simple.html +46 -0
  365. django_cfg/modules/django_tailwind/templatetags/__init__.py +1 -0
  366. django_cfg/modules/django_tailwind/templatetags/tailwind_info.py +185 -0
  367. django_cfg/modules/django_tasks/__init__.py +29 -0
  368. django_cfg/modules/django_tasks/factory.py +127 -0
  369. django_cfg/modules/{django_tasks.py → django_tasks/service.py} +45 -274
  370. django_cfg/modules/django_tasks/settings.py +107 -0
  371. django_cfg/modules/django_telegram/__init__.py +29 -0
  372. django_cfg/modules/{django_telegram.py → django_telegram/service.py} +45 -113
  373. django_cfg/modules/django_telegram/utils.py +62 -0
  374. django_cfg/modules/django_twilio/__init__.py +54 -107
  375. django_cfg/modules/django_twilio/_imports.py +30 -0
  376. django_cfg/modules/django_twilio/base.py +192 -0
  377. django_cfg/modules/django_twilio/email_otp.py +227 -0
  378. django_cfg/modules/django_twilio/sendgrid_service.py +1 -1
  379. django_cfg/modules/django_twilio/simple_service.py +1 -2
  380. django_cfg/modules/django_twilio/sms.py +94 -0
  381. django_cfg/modules/django_twilio/twilio_service.py +2 -3
  382. django_cfg/modules/django_twilio/unified.py +310 -0
  383. django_cfg/modules/django_twilio/utils.py +190 -0
  384. django_cfg/modules/django_twilio/whatsapp.py +137 -0
  385. django_cfg/modules/django_unfold/callbacks/base.py +198 -7
  386. django_cfg/modules/django_unfold/callbacks/main.py +102 -10
  387. django_cfg/modules/django_unfold/dashboard.py +65 -43
  388. django_cfg/modules/django_unfold/models/config.py +13 -12
  389. django_cfg/modules/django_unfold/models/navigation.py +8 -3
  390. django_cfg/modules/django_unfold/models/tabs.py +2 -2
  391. django_cfg/modules/django_unfold/templates/unfold/helpers/app_list.html +102 -0
  392. django_cfg/registry/core.py +24 -26
  393. django_cfg/registry/modules.py +5 -2
  394. django_cfg/registry/services.py +20 -3
  395. django_cfg/registry/third_party.py +8 -8
  396. django_cfg/static/admin/css/dashboard.css +260 -0
  397. django_cfg/static/admin/js/commands.js +171 -0
  398. django_cfg/static/admin/js/dashboard.js +126 -0
  399. django_cfg/templates/admin/components/management_commands.js +375 -0
  400. django_cfg/templates/admin/components/progress_bar.html +18 -23
  401. django_cfg/templates/admin/examples/component_class_example.html +156 -0
  402. django_cfg/templates/admin/index.html +48 -20
  403. django_cfg/templates/admin/index_new.html +106 -0
  404. django_cfg/templates/admin/layouts/base_dashboard.html +60 -0
  405. django_cfg/templates/admin/layouts/dashboard_with_tabs.html +1 -20
  406. django_cfg/templates/admin/sections/commands_section.html +626 -0
  407. django_cfg/templates/admin/sections/overview_section.html +112 -0
  408. django_cfg/templates/admin/sections/stats_section.html +35 -0
  409. django_cfg/templates/admin/sections/system_section.html +99 -0
  410. django_cfg/templates/admin/snippets/components/CHARTS_GUIDE.md +322 -0
  411. django_cfg/templates/admin/snippets/components/activity_tracker.html +85 -47
  412. django_cfg/templates/admin/snippets/components/charts_section.html +154 -64
  413. django_cfg/templates/admin/snippets/components/django_commands.html +3 -3
  414. django_cfg/templates/admin/snippets/components/recent_activity_improved.html +25 -0
  415. django_cfg/templates/admin/snippets/components/recent_users_table.html +1 -1
  416. django_cfg/templates/admin/snippets/components/system_metrics.html +179 -93
  417. django_cfg/templates/admin/snippets/zones/zones_table.html +2 -2
  418. django_cfg/templatetags/django_cfg.py +7 -1
  419. django_cfg/utils/smart_defaults.py +4 -4
  420. django_cfg-1.4.3.dist-info/METADATA +533 -0
  421. {django_cfg-1.3.13.dist-info → django_cfg-1.4.3.dist-info}/RECORD +432 -195
  422. django_cfg/apps/accounts/utils/auth_email_service.py +0 -84
  423. django_cfg/apps/payments/services/providers/nowpayments/parsers.py +0 -879
  424. django_cfg/core/generation.py +0 -621
  425. django_cfg/management/commands/validate_config.py +0 -189
  426. django_cfg/models/database.py +0 -480
  427. django_cfg/models/drf.py +0 -272
  428. django_cfg/models/ngrok.py +0 -122
  429. django_cfg/models/services.py +0 -440
  430. django_cfg/models/tasks.py +0 -550
  431. django_cfg/modules/django_twilio/service.py +0 -942
  432. django_cfg/template_archive/django_sample.zip +0 -0
  433. django_cfg/templates/rest_framework/api.html +0 -12
  434. django_cfg/utils/toolkit.py +0 -703
  435. django_cfg-1.3.13.dist-info/METADATA +0 -1029
  436. /django_cfg/apps/accounts/management/commands/{test_otp.py → otp_test.py} +0 -0
  437. /django_cfg/core/{environment.py → environment/detector.py} +0 -0
  438. /django_cfg/models/{cors.py → api/cors.py} +0 -0
  439. /django_cfg/models/{jwt.py → api/jwt.py} +0 -0
  440. /django_cfg/models/{base.py → base/config.py} +0 -0
  441. /django_cfg/models/{cfg.py → base/module.py} +0 -0
  442. /django_cfg/models/{revolution.py → django/revolution.py} +0 -0
  443. /django_cfg/modules/{dramatiq_setup.py → django_tasks/dramatiq_setup.py} +0 -0
  444. {django_cfg-1.3.13.dist-info → django_cfg-1.4.3.dist-info}/WHEEL +0 -0
  445. {django_cfg-1.3.13.dist-info → django_cfg-1.4.3.dist-info}/entry_points.txt +0 -0
  446. {django_cfg-1.3.13.dist-info → django_cfg-1.4.3.dist-info}/licenses/LICENSE +0 -0
@@ -42,7 +42,7 @@ class OTPViewSet(viewsets.GenericViewSet):
42
42
  500: OTPErrorResponseSerializer,
43
43
  },
44
44
  )
45
- @action(detail=False, methods=["post"], url_path="request")
45
+ @action(detail=False, methods=["post"], url_path="request", url_name="request")
46
46
  def request_otp(self, request):
47
47
  """Request OTP code to email or phone."""
48
48
  serializer = OTPRequestSerializer(data=request.data)
@@ -111,7 +111,7 @@ class OTPViewSet(viewsets.GenericViewSet):
111
111
  410: OTPErrorResponseSerializer,
112
112
  },
113
113
  )
114
- @action(detail=False, methods=["post"], url_path="verify")
114
+ @action(detail=False, methods=["post"], url_path="verify", url_name="verify")
115
115
  def verify_otp(self, request):
116
116
  """Verify OTP code and return JWT tokens."""
117
117
  serializer = OTPVerifySerializer(data=request.data)
@@ -20,7 +20,7 @@ from drf_spectacular.utils import extend_schema, OpenApiParameter
20
20
  from drf_spectacular.types import OpenApiTypes
21
21
  from twilio.request_validator import RequestValidator
22
22
 
23
- from django_cfg.core.config import get_current_config
23
+ from django_cfg.core.state import get_current_config
24
24
  from ..models import TwilioResponse, OTPSecret
25
25
  from ..serializers.webhook import TwilioWebhookSerializer
26
26
 
@@ -14,7 +14,7 @@ from pydantic_ai.models.openai import OpenAIChatModel
14
14
  from pydantic_ai.providers.openrouter import OpenRouterProvider
15
15
  from pydantic_ai.providers.openai import OpenAIProvider
16
16
 
17
- from django_cfg.modules.django_logger import get_logger
17
+ from django_cfg.modules.django_logging import get_logger
18
18
  from django_cfg.modules.base import BaseCfgModule
19
19
  from .exceptions import ExecutionError, ConfigurationError
20
20
 
@@ -0,0 +1,3 @@
1
+ """
2
+ Examples for Django Orchestrator.
3
+ """
@@ -0,0 +1,161 @@
1
+ """
2
+ Simple example demonstrating Django Orchestrator usage.
3
+ """
4
+
5
+ import asyncio
6
+ from dataclasses import dataclass
7
+ from pydantic import BaseModel
8
+ from django.contrib.auth.models import User
9
+
10
+ from django_cfg.modules.django_orchestrator import DjangoAgent, SimpleOrchestrator, DjangoDeps, RunContext
11
+
12
+
13
+ # Define output model
14
+ class GreetingResult(BaseModel):
15
+ """Result from greeting agent."""
16
+ greeting: str
17
+ personalized: bool
18
+ user_info: str
19
+
20
+
21
+ # Create agent
22
+ greeting_agent = DjangoAgent[DjangoDeps, GreetingResult](
23
+ name="greeting_agent",
24
+ deps_type=DjangoDeps,
25
+ output_type=GreetingResult,
26
+ instructions="Generate personalized greetings for users"
27
+ )
28
+
29
+
30
+ # Add tools to agent
31
+ @greeting_agent.tool
32
+ async def get_user_info(ctx: RunContext[DjangoDeps]) -> str:
33
+ """Get user information for personalization."""
34
+ user = ctx.deps.user
35
+ return f"User: {user.username}, Email: {user.email}, Joined: {user.date_joined}"
36
+
37
+
38
+ @greeting_agent.tool
39
+ async def get_time_of_day(ctx: RunContext[DjangoDeps]) -> str:
40
+ """Get current time of day for greeting."""
41
+ from datetime import datetime
42
+ hour = datetime.now().hour
43
+
44
+ if hour < 12:
45
+ return "morning"
46
+ elif hour < 17:
47
+ return "afternoon"
48
+ else:
49
+ return "evening"
50
+
51
+
52
+ async def simple_example():
53
+ """Run simple orchestrator example."""
54
+ print("🤖 Django Orchestrator Simple Example")
55
+ print("=" * 50)
56
+
57
+ # Create test user (in real app, get from request)
58
+ try:
59
+ user = await User.objects.aget(username='testuser')
60
+ except User.DoesNotExist:
61
+ user = await User.objects.acreate_user(
62
+ username='testuser',
63
+ email='test@example.com',
64
+ first_name='Test',
65
+ last_name='User'
66
+ )
67
+
68
+ # Create dependencies
69
+ deps = DjangoDeps(user=user)
70
+
71
+ # Create orchestrator
72
+ orchestrator = SimpleOrchestrator()
73
+ orchestrator.register_agent(greeting_agent)
74
+
75
+ # Execute single agent
76
+ print("\n1. Single Agent Execution:")
77
+ results = await orchestrator.execute(
78
+ pattern="sequential",
79
+ agents=["greeting_agent"],
80
+ prompt="Create a personalized greeting",
81
+ deps=deps
82
+ )
83
+
84
+ result = results[0]
85
+ print(f"✅ Agent: {result.agent_name}")
86
+ print(f"✅ Output: {result.output}")
87
+ print(f"✅ Execution Time: {result.execution_time:.2f}s")
88
+ print(f"✅ Tokens Used: {result.tokens_used}")
89
+
90
+ # Get metrics
91
+ print("\n2. Agent Metrics:")
92
+ metrics = greeting_agent.get_metrics()
93
+ for key, value in metrics.items():
94
+ print(f"📊 {key}: {value}")
95
+
96
+ # Get orchestrator metrics
97
+ print("\n3. Orchestrator Metrics:")
98
+ orch_metrics = orchestrator.get_metrics()
99
+ for key, value in orch_metrics.items():
100
+ print(f"📈 {key}: {value}")
101
+
102
+
103
+ async def multi_agent_example():
104
+ """Run multi-agent orchestrator example."""
105
+ print("\n🤖 Multi-Agent Example")
106
+ print("=" * 30)
107
+
108
+ # Create additional agents
109
+ analyzer_agent = DjangoAgent[DjangoDeps, BaseModel](
110
+ name="content_analyzer",
111
+ deps_type=DjangoDeps,
112
+ output_type=BaseModel,
113
+ instructions="Analyze content sentiment and topics"
114
+ )
115
+
116
+ formatter_agent = DjangoAgent[DjangoDeps, BaseModel](
117
+ name="content_formatter",
118
+ deps_type=DjangoDeps,
119
+ output_type=BaseModel,
120
+ instructions="Format content for display"
121
+ )
122
+
123
+ # Create orchestrator
124
+ orchestrator = SimpleOrchestrator()
125
+ orchestrator.register_agent(analyzer_agent)
126
+ orchestrator.register_agent(formatter_agent)
127
+
128
+ # Get user
129
+ user = await User.objects.aget(username='testuser')
130
+ deps = DjangoDeps(user=user)
131
+
132
+ # Execute sequential workflow
133
+ print("\n1. Sequential Workflow:")
134
+ results = await orchestrator.execute(
135
+ pattern="sequential",
136
+ agents=["content_analyzer", "content_formatter"],
137
+ prompt="Analyze and format this content: Hello world!",
138
+ deps=deps
139
+ )
140
+
141
+ for i, result in enumerate(results, 1):
142
+ print(f"Step {i} - {result.agent_name}: {result.success}")
143
+
144
+ # Execute parallel workflow
145
+ print("\n2. Parallel Workflow:")
146
+ results = await orchestrator.execute(
147
+ pattern="parallel",
148
+ agents=["content_analyzer", "content_formatter"],
149
+ prompt="Process content in parallel",
150
+ deps=deps,
151
+ max_concurrent=2
152
+ )
153
+
154
+ successful = sum(1 for r in results if r.success)
155
+ print(f"✅ {successful}/{len(results)} agents completed successfully")
156
+
157
+
158
+ if __name__ == "__main__":
159
+ # Run examples
160
+ asyncio.run(simple_example())
161
+ asyncio.run(multi_agent_example())
@@ -21,13 +21,13 @@ from django.utils import timezone
21
21
  logger = logging.getLogger(__name__)
22
22
 
23
23
 
24
- def is_superuser(user):
25
- """Check if user is superuser."""
26
- return user.is_authenticated and user.is_superuser
24
+ def is_staff_user(user):
25
+ """Check if user is staff member."""
26
+ return user.is_authenticated and user.is_staff
27
27
 
28
28
 
29
29
  @require_http_methods(["GET"])
30
- @user_passes_test(is_superuser)
30
+ @user_passes_test(is_staff_user)
31
31
  def list_commands_view(request):
32
32
  """
33
33
  List all available Django management commands.
@@ -81,7 +81,7 @@ def list_commands_view(request):
81
81
 
82
82
  @csrf_exempt
83
83
  @require_http_methods(["POST"])
84
- @user_passes_test(is_superuser)
84
+ @user_passes_test(is_staff_user)
85
85
  def execute_command_view(request):
86
86
  """
87
87
  Execute a Django management command and stream output in real-time.
@@ -117,106 +117,89 @@ def execute_command_view(request):
117
117
  "error": f"Command '{command_name}' not found",
118
118
  "available_commands": list(available_commands.keys()),
119
119
  }, status=400)
120
-
121
- # Security check - block dangerous commands
122
- dangerous_commands = [
123
- "flush", "sqlflush", "dbshell", "shell", "shell_plus",
124
- "reset_db", "migrate", "makemigrations", "loaddata"
125
- ]
126
-
127
- if command_name in dangerous_commands:
120
+
121
+ # Security check - use same filtering as dashboard
122
+ from django_cfg.modules.django_unfold.callbacks.base import is_command_allowed
123
+
124
+ app_name = available_commands.get(command_name)
125
+ if not is_command_allowed(command_name, app_name):
128
126
  return JsonResponse({
129
- "status": "error",
130
- "error": f"Command '{command_name}' is not allowed via API for security reasons",
131
- "suggestion": "Use django_cfg management commands instead: show_config, test_email",
127
+ "status": "error",
128
+ "error": f"Command '{command_name}' is not allowed via web interface for security reasons",
129
+ "suggestion": "Only safe django_cfg commands and whitelisted utilities can be executed via web.",
132
130
  }, status=403)
133
131
 
134
132
  # Create streaming response generator
135
133
  def stream_command_execution():
136
134
  """Generator that yields command output in SSE format."""
137
135
  start_time = time.time()
138
-
136
+
139
137
  # Send start event
140
138
  yield f"data: {json.dumps({'type': 'start', 'command': command_name, 'args': args})}\n\n"
141
-
139
+
142
140
  try:
143
- # Execute command with subprocess for real-time output
144
- import subprocess
141
+ # Capture command output using StringIO
142
+ from io import StringIO
145
143
  import sys
146
- import os
147
-
148
- # Find Django project root and manage.py
149
- from django.conf import settings
150
-
151
- # Try to find manage.py in project root
152
- if hasattr(settings, 'BASE_DIR'):
153
- project_root = settings.BASE_DIR
154
- manage_py_path = os.path.join(project_root, 'manage.py')
155
- else:
156
- # Fallback: search for manage.py
157
- current_dir = os.path.dirname(os.path.abspath(__file__))
158
- while current_dir != '/':
159
- manage_py_path = os.path.join(current_dir, 'manage.py')
160
- if os.path.exists(manage_py_path):
161
- project_root = current_dir
162
- break
163
- current_dir = os.path.dirname(current_dir)
164
- else:
165
- raise Exception("Could not find manage.py")
166
-
167
- # Build command
168
- cmd = [sys.executable, manage_py_path, command_name] + args
169
-
170
- # Add options to command
171
- for key, value in options.items():
172
- if key.startswith('--'):
173
- cmd.append(key)
174
- if value is not True: # Boolean flags don't need values
175
- cmd.append(str(value))
176
- else:
177
- cmd.append(f"--{key}")
178
- if value is not True:
179
- cmd.append(str(value))
180
-
181
- # Start process
182
- process = subprocess.Popen(
183
- cmd,
184
- stdout=subprocess.PIPE,
185
- stderr=subprocess.STDOUT,
186
- universal_newlines=True,
187
- bufsize=1,
188
- cwd=project_root
189
- )
190
-
144
+
145
+ # Create output buffer
146
+ output_buffer = StringIO()
147
+
148
+ # Redirect stdout/stderr to buffer
149
+ old_stdout = sys.stdout
150
+ old_stderr = sys.stderr
151
+ sys.stdout = output_buffer
152
+ sys.stderr = output_buffer
153
+
154
+ try:
155
+ # Execute Django command directly using call_command
156
+ call_command(command_name, *args, **options)
157
+ return_code = 0
158
+ except Exception as e:
159
+ # Command execution failed
160
+ output_buffer.write(f"\nError: {str(e)}\n")
161
+ return_code = 1
162
+ finally:
163
+ # Restore stdout/stderr
164
+ sys.stdout = old_stdout
165
+ sys.stderr = old_stderr
166
+
167
+ # Get all output
168
+ output = output_buffer.getvalue()
169
+
191
170
  # Stream output line by line
192
- for line in iter(process.stdout.readline, ''):
193
- if line:
194
- line = line.rstrip('\n\r')
195
- yield f"data: {json.dumps({'type': 'output', 'line': line})}\n\n"
196
-
197
- # Wait for process to complete
198
- return_code = process.wait()
171
+ if output:
172
+ for line in output.split('\n'):
173
+ if line.strip():
174
+ yield f"data: {json.dumps({'type': 'output', 'line': line})}\n\n"
175
+
199
176
  execution_time = time.time() - start_time
200
-
177
+
201
178
  # Send completion event
202
179
  yield f"data: {json.dumps({'type': 'complete', 'return_code': return_code, 'execution_time': round(execution_time, 2)})}\n\n"
203
-
180
+
204
181
  # Log command execution
205
- logger.info(
206
- f"Command executed: {command_name} {' '.join(args)} "
207
- f"by user {request.user.username} in {execution_time:.2f}s with exit code {return_code}"
208
- )
209
-
182
+ if return_code == 0:
183
+ logger.info(
184
+ f"Command executed: {command_name} {' '.join(args)} "
185
+ f"by user {request.user.username} in {execution_time:.2f}s"
186
+ )
187
+ else:
188
+ logger.error(
189
+ f"Command failed: {command_name} {' '.join(args)} "
190
+ f"by user {request.user.username} in {execution_time:.2f}s"
191
+ )
192
+
210
193
  except Exception as cmd_error:
211
194
  execution_time = time.time() - start_time
212
-
195
+
213
196
  logger.error(
214
197
  f"Command failed: {command_name} {' '.join(args)} "
215
198
  f"by user {request.user.username}: {cmd_error}"
216
199
  )
217
-
200
+
218
201
  # Send error event
219
- yield f"data: {json.dumps({'type': 'error', 'error': str(cmd_error), 'execution_time': round(execution_time, 2)})}\n\n"
202
+ yield f"data: {json.dumps({'type': 'error', 'message': str(cmd_error), 'execution_time': round(execution_time, 2)})}\n\n"
220
203
 
221
204
  # Return streaming response
222
205
  response = StreamingHttpResponse(
@@ -243,7 +226,7 @@ def execute_command_view(request):
243
226
 
244
227
 
245
228
  @require_http_methods(["GET"])
246
- @user_passes_test(is_superuser)
229
+ @user_passes_test(is_staff_user)
247
230
  def command_help_view(request, command_name):
248
231
  """
249
232
  Get help information for a specific command.
@@ -0,0 +1,269 @@
1
+ """
2
+ Django CFG Health Check DRF Views
3
+
4
+ DRF browsable API views with Tailwind theme support.
5
+ """
6
+
7
+ import os
8
+ import time
9
+ import psutil
10
+ from datetime import datetime
11
+ from typing import Dict, Any
12
+
13
+ from django.conf import settings
14
+ from django.db import connections
15
+ from django.core.cache import cache
16
+ from django.utils import timezone
17
+
18
+ from rest_framework.views import APIView
19
+ from rest_framework.response import Response
20
+ from rest_framework import status
21
+ from rest_framework.permissions import AllowAny
22
+
23
+ from django_cfg.core.integration import get_current_version
24
+ from .serializers import HealthCheckSerializer, QuickHealthSerializer
25
+
26
+
27
+ class DRFHealthCheckView(APIView):
28
+ """
29
+ Django CFG comprehensive health check endpoint with DRF Browsable API.
30
+
31
+ Auto-discovers configuration from DjangoConfig and checks:
32
+ - All configured databases
33
+ - Cache connectivity
34
+ - System resources
35
+ - Configuration status
36
+
37
+ This endpoint uses DRF Browsable API with Tailwind CSS theme! 🎨
38
+ """
39
+
40
+ permission_classes = [AllowAny] # Public endpoint
41
+ serializer_class = HealthCheckSerializer # For schema generation
42
+
43
+ def get(self, request):
44
+ """Return comprehensive health check data."""
45
+ # Get DjangoConfig instance
46
+ try:
47
+ config = getattr(settings, 'config', None)
48
+
49
+ health_data = {
50
+ "status": "healthy",
51
+ "timestamp": timezone.now(),
52
+ "service": config.project_name if config else "Django CFG",
53
+ "version": get_current_version(),
54
+ "checks": {}
55
+ }
56
+ except Exception:
57
+ health_data = {
58
+ "status": "healthy",
59
+ "timestamp": timezone.now(),
60
+ "service": "Django CFG",
61
+ "version": get_current_version(),
62
+ "checks": {}
63
+ }
64
+
65
+ # Database connectivity check
66
+ try:
67
+ db_status = self._check_databases()
68
+ health_data["checks"]["databases"] = db_status
69
+ except Exception as e:
70
+ health_data["checks"]["databases"] = {
71
+ "status": "error",
72
+ "error": str(e)
73
+ }
74
+ health_data["status"] = "unhealthy"
75
+
76
+ # Cache availability check
77
+ try:
78
+ cache_status = self._check_cache()
79
+ health_data["checks"]["cache"] = cache_status
80
+ except Exception as e:
81
+ health_data["checks"]["cache"] = {
82
+ "status": "error",
83
+ "error": str(e)
84
+ }
85
+ if health_data["status"] != "unhealthy":
86
+ health_data["status"] = "degraded"
87
+
88
+ # System resources check
89
+ try:
90
+ system_status = self._check_system_resources()
91
+ health_data["checks"]["system"] = system_status
92
+ except Exception as e:
93
+ health_data["checks"]["system"] = {
94
+ "status": "error",
95
+ "error": str(e)
96
+ }
97
+
98
+ # Environment info
99
+ health_data["environment"] = {
100
+ "debug": getattr(settings, 'DEBUG', False),
101
+ "django_env": os.getenv("DJANGO_ENV", "development"),
102
+ "python_version": f"{os.sys.version_info.major}.{os.sys.version_info.minor}.{os.sys.version_info.micro}",
103
+ }
104
+
105
+ # Return appropriate HTTP status
106
+ http_status = status.HTTP_200_OK
107
+ if health_data["status"] == "unhealthy":
108
+ http_status = status.HTTP_503_SERVICE_UNAVAILABLE
109
+ elif health_data["status"] == "degraded":
110
+ http_status = status.HTTP_200_OK # Still operational
111
+
112
+ return Response(health_data, status=http_status)
113
+
114
+ def _check_databases(self) -> Dict[str, Any]:
115
+ """Check all configured database connections."""
116
+ db_results = {}
117
+
118
+ # Get all configured databases
119
+ database_names = list(getattr(settings, 'DATABASES', {}).keys())
120
+
121
+ for db_name in database_names:
122
+ try:
123
+ start_time = time.time()
124
+ conn = connections[db_name]
125
+
126
+ with conn.cursor() as cursor:
127
+ cursor.execute("SELECT 1")
128
+ cursor.fetchone()
129
+
130
+ response_time = (time.time() - start_time) * 1000 # ms
131
+
132
+ db_results[db_name] = {
133
+ "status": "healthy",
134
+ "response_time_ms": round(response_time, 2),
135
+ "engine": conn.settings_dict.get("ENGINE", "unknown"),
136
+ }
137
+
138
+ except Exception as e:
139
+ db_results[db_name] = {
140
+ "status": "error",
141
+ "error": str(e)[:100], # Truncate long errors
142
+ }
143
+
144
+ # Overall database status
145
+ all_healthy = all(
146
+ db["status"] == "healthy"
147
+ for db in db_results.values()
148
+ ) if db_results else False
149
+
150
+ return {
151
+ "status": "healthy" if all_healthy else "error",
152
+ "databases": db_results,
153
+ "total_databases": len(db_results),
154
+ }
155
+
156
+ def _check_cache(self) -> Dict[str, Any]:
157
+ """Check cache connectivity and performance."""
158
+ try:
159
+ test_key = "django_cfg_health_check"
160
+ test_value = f"test_{int(time.time())}"
161
+
162
+ # Test cache write
163
+ start_time = time.time()
164
+ cache.set(test_key, test_value, timeout=60)
165
+ write_time = (time.time() - start_time) * 1000
166
+
167
+ # Test cache read
168
+ start_time = time.time()
169
+ cached_value = cache.get(test_key)
170
+ read_time = (time.time() - start_time) * 1000
171
+
172
+ # Cleanup
173
+ cache.delete(test_key)
174
+
175
+ if cached_value == test_value:
176
+ return {
177
+ "status": "healthy",
178
+ "write_time_ms": round(write_time, 2),
179
+ "read_time_ms": round(read_time, 2),
180
+ "backend": getattr(settings, "CACHES", {}).get("default", {}).get("BACKEND", "unknown"),
181
+ }
182
+ else:
183
+ return {
184
+ "status": "error",
185
+ "error": "Cache read/write mismatch"
186
+ }
187
+
188
+ except Exception as e:
189
+ return {
190
+ "status": "error",
191
+ "error": str(e)
192
+ }
193
+
194
+ def _check_system_resources(self) -> Dict[str, Any]:
195
+ """Check system resource usage."""
196
+ try:
197
+ # CPU usage
198
+ cpu_percent = psutil.cpu_percent(interval=1)
199
+
200
+ # Memory usage
201
+ memory = psutil.virtual_memory()
202
+
203
+ # Disk usage
204
+ disk = psutil.disk_usage('/')
205
+
206
+ # System uptime
207
+ boot_time = datetime.fromtimestamp(psutil.boot_time())
208
+ uptime = datetime.now() - boot_time
209
+
210
+ return {
211
+ "status": "healthy",
212
+ "cpu": {
213
+ "percent": cpu_percent,
214
+ "count": psutil.cpu_count(),
215
+ },
216
+ "memory": {
217
+ "percent": memory.percent,
218
+ "used_gb": round(memory.used / (1024**3), 2),
219
+ "total_gb": round(memory.total / (1024**3), 2),
220
+ },
221
+ "disk": {
222
+ "percent": round((disk.used / disk.total) * 100, 2),
223
+ "used_gb": round(disk.used / (1024**3), 2),
224
+ "total_gb": round(disk.total / (1024**3), 2),
225
+ },
226
+ "uptime": {
227
+ "days": uptime.days,
228
+ "hours": uptime.seconds // 3600,
229
+ "boot_time": boot_time.isoformat(),
230
+ },
231
+ "process_count": len(psutil.pids()),
232
+ }
233
+
234
+ except Exception as e:
235
+ return {
236
+ "status": "error",
237
+ "error": str(e)
238
+ }
239
+
240
+
241
+ class DRFQuickHealthView(APIView):
242
+ """
243
+ Quick health check for load balancers with DRF Browsable API.
244
+
245
+ This endpoint uses DRF Browsable API with Tailwind CSS theme! 🎨
246
+ """
247
+
248
+ permission_classes = [AllowAny] # Public endpoint
249
+ serializer_class = QuickHealthSerializer # For schema generation
250
+
251
+ def get(self, request):
252
+ """Return minimal health status."""
253
+ try:
254
+ # Just check main database
255
+ conn = connections["default"]
256
+ with conn.cursor() as cursor:
257
+ cursor.execute("SELECT 1")
258
+
259
+ return Response({
260
+ "status": "ok",
261
+ "timestamp": timezone.now(),
262
+ })
263
+
264
+ except Exception as e:
265
+ return Response({
266
+ "status": "error",
267
+ "error": str(e),
268
+ "timestamp": timezone.now(),
269
+ }, status=status.HTTP_503_SERVICE_UNAVAILABLE)