django-cfg 1.1.61__tar.gz → 1.1.63__tar.gz

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 (265) hide show
  1. {django_cfg-1.1.61 → django_cfg-1.1.63}/PKG-INFO +145 -4
  2. {django_cfg-1.1.61 → django_cfg-1.1.63}/README.md +144 -3
  3. {django_cfg-1.1.61 → django_cfg-1.1.63}/pyproject.toml +1 -1
  4. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/__init__.py +1 -1
  5. django_cfg-1.1.63/src/django_cfg/management/commands/rundramatiq.py +241 -0
  6. django_cfg-1.1.63/src/django_cfg/modules/django_tasks.py +373 -0
  7. django_cfg-1.1.63/src/django_cfg/modules/dramatiq_setup.py +16 -0
  8. django_cfg-1.1.61/src/django_cfg/management/commands/rundramatiq.py +0 -269
  9. django_cfg-1.1.61/src/django_cfg/modules/django_tasks.py +0 -747
  10. {django_cfg-1.1.61 → django_cfg-1.1.63}/.gitignore +0 -0
  11. {django_cfg-1.1.61 → django_cfg-1.1.63}/LICENSE +0 -0
  12. {django_cfg-1.1.61 → django_cfg-1.1.63}/MANIFEST.in +0 -0
  13. {django_cfg-1.1.61 → django_cfg-1.1.63}/requirements-dev.txt +0 -0
  14. {django_cfg-1.1.61 → django_cfg-1.1.63}/requirements-test.txt +0 -0
  15. {django_cfg-1.1.61 → django_cfg-1.1.63}/requirements.txt +0 -0
  16. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/__init__.py +0 -0
  17. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/README.md +0 -0
  18. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/__init__.py +0 -0
  19. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/admin/__init__.py +0 -0
  20. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/admin/activity.py +0 -0
  21. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/admin/filters.py +0 -0
  22. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/admin/group.py +0 -0
  23. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/admin/inlines.py +0 -0
  24. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/admin/otp.py +0 -0
  25. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/admin/registration_source.py +0 -0
  26. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/admin/twilio_response.py +0 -0
  27. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/admin/user.py +0 -0
  28. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/apps.py +0 -0
  29. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/management/commands/test_otp.py +0 -0
  30. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/managers/__init__.py +0 -0
  31. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/managers/user_manager.py +0 -0
  32. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/migrations/0001_initial.py +0 -0
  33. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/migrations/0002_add_phone_otp_clean.py +0 -0
  34. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/migrations/0003_twilioresponse.py +0 -0
  35. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/migrations/0004_delete_twilioresponse.py +0 -0
  36. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/migrations/__init__.py +0 -0
  37. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/models.py +0 -0
  38. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/serializers/__init__.py +0 -0
  39. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/serializers/otp.py +0 -0
  40. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/serializers/profile.py +0 -0
  41. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/serializers/webhook.py +0 -0
  42. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/services/__init__.py +0 -0
  43. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/services/activity_service.py +0 -0
  44. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/services/otp_service.py +0 -0
  45. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/signals.py +0 -0
  46. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/templates/emails/base_email.html +0 -0
  47. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/templates/emails/base_email.txt +0 -0
  48. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/templates/emails/otp_email.html +0 -0
  49. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/templates/emails/otp_email.txt +0 -0
  50. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/templates/emails/welcome_email.html +0 -0
  51. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/templates/emails/welcome_email.txt +0 -0
  52. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/urls.py +0 -0
  53. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/utils/notifications.py +0 -0
  54. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/views/__init__.py +0 -0
  55. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/views/otp.py +0 -0
  56. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/views/profile.py +0 -0
  57. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/accounts/views/webhook.py +0 -0
  58. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/api/__init__.py +0 -0
  59. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/api/commands/__init__.py +0 -0
  60. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/api/commands/urls.py +0 -0
  61. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/api/commands/views.py +0 -0
  62. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/api/health/__init__.py +0 -0
  63. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/api/health/urls.py +0 -0
  64. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/api/health/views.py +0 -0
  65. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/leads/README.md +0 -0
  66. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/leads/__init__.py +0 -0
  67. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/leads/admin.py +0 -0
  68. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/leads/apps.py +0 -0
  69. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/leads/migrations/0001_initial.py +0 -0
  70. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/leads/migrations/__init__.py +0 -0
  71. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/leads/models.py +0 -0
  72. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/leads/serializers.py +0 -0
  73. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/leads/signals.py +0 -0
  74. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/leads/tests.py +0 -0
  75. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/leads/urls.py +0 -0
  76. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/leads/views.py +0 -0
  77. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/newsletter/README.md +0 -0
  78. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/newsletter/__init__.py +0 -0
  79. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/newsletter/admin.py +0 -0
  80. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/newsletter/admin_filters.py +0 -0
  81. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/newsletter/apps.py +0 -0
  82. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/newsletter/management/__init__.py +0 -0
  83. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/newsletter/management/commands/__init__.py +0 -0
  84. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/newsletter/management/commands/test_newsletter.py +0 -0
  85. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/newsletter/managers/README.md +0 -0
  86. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/newsletter/managers/__init__.py +0 -0
  87. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/newsletter/migrations/0001_initial.py +0 -0
  88. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/newsletter/migrations/__init__.py +0 -0
  89. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/newsletter/models.py +0 -0
  90. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/newsletter/serializers.py +0 -0
  91. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/newsletter/services/email_service.py +0 -0
  92. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/newsletter/signals.py +0 -0
  93. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/newsletter/urls.py +0 -0
  94. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/newsletter/utils/__init__.py +0 -0
  95. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/newsletter/views/__init__.py +0 -0
  96. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/newsletter/views/campaigns.py +0 -0
  97. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/newsletter/views/emails.py +0 -0
  98. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/newsletter/views/newsletters.py +0 -0
  99. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/newsletter/views/subscriptions.py +0 -0
  100. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/newsletter/views/tracking.py +0 -0
  101. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/support/__init__.py +0 -0
  102. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/support/admin.py +0 -0
  103. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/support/admin_filters.py +0 -0
  104. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/support/apps.py +0 -0
  105. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/support/managers/message_manager.py +0 -0
  106. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/support/managers/ticket_manager.py +0 -0
  107. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/support/migrations/0001_initial.py +0 -0
  108. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/support/migrations/0002_alter_message_ticket.py +0 -0
  109. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/support/migrations/__init__.py +0 -0
  110. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/support/models.py +0 -0
  111. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/support/serializers.py +0 -0
  112. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/support/signals.py +0 -0
  113. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/support/templates/support/chat/access_denied.html +0 -0
  114. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/support/templates/support/chat/ticket_chat.html +0 -0
  115. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/support/urls.py +0 -0
  116. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/support/utils/__init__.py +0 -0
  117. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/support/utils/support_email_service.py +0 -0
  118. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/support/views/__init__.py +0 -0
  119. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/support/views/admin.py +0 -0
  120. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/support/views/api.py +0 -0
  121. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/support/views/chat.py +0 -0
  122. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/tasks/__init__.py +0 -0
  123. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/tasks/admin.py +0 -0
  124. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/tasks/apps.py +0 -0
  125. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/tasks/serializers.py +0 -0
  126. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/tasks/static/tasks/css/dashboard.css +0 -0
  127. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/tasks/static/tasks/js/api.js +0 -0
  128. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/tasks/static/tasks/js/dashboard.js +0 -0
  129. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/tasks/static/tasks/js/modals.js +0 -0
  130. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/tasks/static/tasks/js/notifications.js +0 -0
  131. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/tasks/static/tasks/js/task-monitor.js +0 -0
  132. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/tasks/static/tasks/js/theme.js +0 -0
  133. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/tasks/templates/tasks/base.html +0 -0
  134. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/tasks/templates/tasks/components/info_cards.html +0 -0
  135. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/tasks/templates/tasks/components/management_actions.html +0 -0
  136. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/tasks/templates/tasks/components/overview_tab.html +0 -0
  137. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/tasks/templates/tasks/components/queues_tab.html +0 -0
  138. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/tasks/templates/tasks/components/status_cards.html +0 -0
  139. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/tasks/templates/tasks/components/tab_navigation.html +0 -0
  140. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/tasks/templates/tasks/components/task_details_modal.html +0 -0
  141. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/tasks/templates/tasks/components/tasks_tab.html +0 -0
  142. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/tasks/templates/tasks/components/workers_tab.html +0 -0
  143. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/tasks/templates/tasks/dashboard.html +0 -0
  144. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/tasks/urls.py +0 -0
  145. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/tasks/views.py +0 -0
  146. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps/urls.py +0 -0
  147. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/apps.py +0 -0
  148. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/archive/django_sample.zip +0 -0
  149. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/cli/README.md +0 -0
  150. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/cli/__init__.py +0 -0
  151. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/cli/commands/__init__.py +0 -0
  152. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/cli/commands/create_project.py +0 -0
  153. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/cli/commands/info.py +0 -0
  154. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/cli/main.py +0 -0
  155. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/cli/utils.py +0 -0
  156. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/core/__init__.py +0 -0
  157. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/core/config.py +0 -0
  158. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/core/environment.py +0 -0
  159. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/core/generation.py +0 -0
  160. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/core/validation.py +0 -0
  161. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/exceptions.py +0 -0
  162. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/integration.py +0 -0
  163. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/management/__init__.py +0 -0
  164. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/management/commands/__init__.py +0 -0
  165. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/management/commands/check_settings.py +0 -0
  166. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/management/commands/clear_constance.py +0 -0
  167. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/management/commands/create_token.py +0 -0
  168. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/management/commands/generate.py +0 -0
  169. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/management/commands/list_urls.py +0 -0
  170. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/management/commands/migrator.py +0 -0
  171. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/management/commands/runserver_ngrok.py +0 -0
  172. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/management/commands/script.py +0 -0
  173. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/management/commands/show_config.py +0 -0
  174. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/management/commands/show_urls.py +0 -0
  175. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/management/commands/superuser.py +0 -0
  176. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/management/commands/task_clear.py +0 -0
  177. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/management/commands/task_status.py +0 -0
  178. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/management/commands/test_email.py +0 -0
  179. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/management/commands/test_telegram.py +0 -0
  180. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/management/commands/test_twilio.py +0 -0
  181. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/management/commands/tree.py +0 -0
  182. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/management/commands/validate_config.py +0 -0
  183. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/middleware/README.md +0 -0
  184. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/middleware/__init__.py +0 -0
  185. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/middleware/user_activity.py +0 -0
  186. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/models/__init__.py +0 -0
  187. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/models/cache.py +0 -0
  188. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/models/constance.py +0 -0
  189. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/models/database.py +0 -0
  190. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/models/drf.py +0 -0
  191. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/models/jwt.py +0 -0
  192. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/models/limits.py +0 -0
  193. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/models/ngrok.py +0 -0
  194. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/models/revolution.py +0 -0
  195. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/models/services.py +0 -0
  196. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/models/tasks.py +0 -0
  197. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/models/unfold.py +0 -0
  198. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/__init__.py +0 -0
  199. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/base.py +0 -0
  200. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_currency/README.md +0 -0
  201. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_currency/__init__.py +0 -0
  202. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_currency/cache.py +0 -0
  203. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_currency/converter.py +0 -0
  204. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_currency/service.py +0 -0
  205. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_email.py +0 -0
  206. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_llm/README.md +0 -0
  207. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_llm/__init__.py +0 -0
  208. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_llm/example.py +0 -0
  209. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_llm/llm/__init__.py +0 -0
  210. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_llm/llm/cache.py +0 -0
  211. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_llm/llm/client.py +0 -0
  212. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_llm/llm/costs.py +0 -0
  213. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_llm/llm/extractor.py +0 -0
  214. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_llm/llm/models_cache.py +0 -0
  215. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_llm/llm/tokenizer.py +0 -0
  216. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_llm/translator/__init__.py +0 -0
  217. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_llm/translator/cache.py +0 -0
  218. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_llm/translator/translator.py +0 -0
  219. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_logger.py +0 -0
  220. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_ngrok.py +0 -0
  221. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_telegram.py +0 -0
  222. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_twilio/README.md +0 -0
  223. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_twilio/__init__.py +0 -0
  224. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_twilio/exceptions.py +0 -0
  225. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_twilio/models.py +0 -0
  226. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_twilio/sendgrid_service.py +0 -0
  227. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_twilio/service.py +0 -0
  228. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_twilio/simple_service.py +0 -0
  229. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_twilio/templates/guide.md +0 -0
  230. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_twilio/templates/sendgrid_otp_email.html +0 -0
  231. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_twilio/templates/sendgrid_test_data.json +0 -0
  232. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/django_twilio/twilio_service.py +0 -0
  233. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/logger.py +0 -0
  234. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/unfold/__init__.py +0 -0
  235. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/unfold/callbacks.py +0 -0
  236. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/unfold/dashboard.py +0 -0
  237. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/unfold/models.py +0 -0
  238. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/unfold/system_monitor.py +0 -0
  239. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/modules/unfold/tailwind.py +0 -0
  240. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/routers.py +0 -0
  241. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/templates/__init__.py +0 -0
  242. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/templates/admin/index.html +0 -0
  243. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/templates/admin/layouts/dashboard_with_tabs.html +0 -0
  244. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/templates/admin/snippets/components/activity_tracker.html +0 -0
  245. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/templates/admin/snippets/components/charts_section.html +0 -0
  246. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/templates/admin/snippets/components/django_commands.html +0 -0
  247. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/templates/admin/snippets/components/quick_actions.html +0 -0
  248. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/templates/admin/snippets/components/recent_activity.html +0 -0
  249. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/templates/admin/snippets/components/recent_users_table.html +0 -0
  250. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/templates/admin/snippets/components/stats_cards.html +0 -0
  251. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/templates/admin/snippets/components/stats_tiles.html +0 -0
  252. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/templates/admin/snippets/components/system_health.html +0 -0
  253. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/templates/admin/snippets/components/system_metrics.html +0 -0
  254. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/templates/admin/snippets/components/user_permissions.html +0 -0
  255. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/templates/admin/snippets/tabs/app_stats_tab.html +0 -0
  256. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/templates/admin/snippets/tabs/commands_tab.html +0 -0
  257. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/templates/admin/snippets/tabs/overview_tab.html +0 -0
  258. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/templates/admin/snippets/tabs/stats_tab.html +0 -0
  259. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/templates/admin/snippets/tabs/users_tab.html +0 -0
  260. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/templates/admin/snippets/zones/zones_table.html +0 -0
  261. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/templates/emails/base_email.html +0 -0
  262. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/utils/__init__.py +0 -0
  263. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/utils/path_resolution.py +0 -0
  264. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/utils/smart_defaults.py +0 -0
  265. {django_cfg-1.1.61 → django_cfg-1.1.63}/src/django_cfg/version_check.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-cfg
3
- Version: 1.1.61
3
+ Version: 1.1.63
4
4
  Summary: 🚀 Production-ready Django configuration framework with type-safe settings, smart automation, and modern developer experience
5
5
  Project-URL: Homepage, https://github.com/markolofsen/django-cfg
6
6
  Project-URL: Documentation, https://django-cfg.readthedocs.io
@@ -173,7 +173,7 @@ python manage.py runserver
173
173
  - ✅ **Newsletter campaigns** with email tracking
174
174
  - ✅ **Lead management** system with CRM integration
175
175
  - ✅ **Multi-database routing** and connection pooling
176
- - ✅ **Background task processing** with Dramatiq
176
+ - ✅ **Background task processing** with production-ready Dramatiq integration
177
177
  - ✅ **Webhook testing** with built-in ngrok integration
178
178
  - ✅ **Type-safe configuration** with full IDE support
179
179
 
@@ -413,8 +413,137 @@ Automatic dev/staging/production detection with appropriate defaults.
413
413
  ### 🌐 **Built-in Ngrok Integration**
414
414
  Instant webhook testing with zero-config ngrok tunnels for development.
415
415
 
416
- ### 🔄 **Background Task Processing**
417
- Built-in Dramatiq integration for reliable background job processing with Redis.
416
+ ### 🔄 **Background Task Processing** %%PRIORITY:HIGH%%
417
+
418
+ Django-CFG includes a complete Dramatiq integration for reliable background job processing with automatic Redis configuration, worker management, and task monitoring.
419
+
420
+ #### Features
421
+ - **🚀 Zero Configuration** - Automatic Redis broker setup and queue management
422
+ - **⚡ Smart Worker Management** - Built-in `rundramatiq` command with Django settings integration
423
+ - **🔧 Type-Safe Task Definition** - Full IDE support for task creation and scheduling
424
+ - **📊 Task Monitoring** - Built-in commands for queue status and task management
425
+ - **🐳 Docker Ready** - Pre-configured Docker containers for production deployment
426
+ - **🛡️ Production Tested** - Battle-tested configuration used in production environments
427
+
428
+ #### Quick Setup
429
+ ```python
430
+ from django_cfg import DjangoConfig
431
+
432
+ class MyConfig(DjangoConfig):
433
+ project_name: str = "My App"
434
+
435
+ # Dramatiq configuration (automatic)
436
+ redis_url: str = "redis://localhost:6379/2" # Separate DB for tasks
437
+
438
+ # Optional: Custom task settings
439
+ dramatiq: DramatiqConfig = DramatiqConfig(
440
+ processes=2, # Worker processes
441
+ threads=4, # Threads per process
442
+ redis_db=2, # Redis database for tasks
443
+ queues=["default", "high", "low"] # Available queues
444
+ )
445
+
446
+ config = MyConfig()
447
+ ```
448
+
449
+ #### Task Definition
450
+ ```python
451
+ import dramatiq
452
+ from django_cfg.modules.django_tasks import get_broker
453
+
454
+ # Tasks are automatically discovered from your apps
455
+ @dramatiq.actor(queue_name="high", max_retries=3)
456
+ def process_document(document_id: str) -> dict:
457
+ """Process document asynchronously with full Django context."""
458
+ from myapp.models import Document
459
+
460
+ document = Document.objects.get(id=document_id)
461
+ # Your processing logic here
462
+ document.status = "processed"
463
+ document.save()
464
+
465
+ return {"status": "completed", "document_id": document_id}
466
+
467
+ # Queue the task
468
+ process_document.send(document_id="123")
469
+ ```
470
+
471
+ #### Management Commands
472
+ ```bash
473
+ # Start Dramatiq workers with Django settings
474
+ python manage.py rundramatiq --processes 4 --threads 8
475
+
476
+ # Monitor task queues and status
477
+ python manage.py task_status --queue high
478
+
479
+ # Clear specific queues
480
+ python manage.py task_clear --queue default
481
+
482
+ # Test task processing pipeline
483
+ python manage.py test_tasks
484
+ ```
485
+
486
+ #### Docker Integration
487
+ ```yaml
488
+ # docker-compose.yml (automatically generated)
489
+ services:
490
+ app-dramatiq:
491
+ build: .
492
+ command: ["python", "manage.py", "rundramatiq"]
493
+ environment:
494
+ - DRAMATIQ_PROCESSES=2
495
+ - DRAMATIQ_THREADS=4
496
+ - DRAMATIQ_QUEUES=default,high,low
497
+ depends_on:
498
+ - redis
499
+ - postgres
500
+ ```
501
+
502
+ #### Production Features
503
+ - **🔄 Automatic Restart** - Workers restart on code changes in development
504
+ - **📈 Scaling** - Easy horizontal scaling with multiple worker containers
505
+ - **🛡️ Error Handling** - Built-in retry logic and dead letter queues
506
+ - **📊 Monitoring** - Integration with Django admin for task monitoring
507
+ - **⚡ Performance** - Optimized Redis configuration for high throughput
508
+
509
+ #### Real-World Example
510
+ ```python
511
+ # Document processing pipeline
512
+ @dramatiq.actor(queue_name="knowledge", max_retries=2)
513
+ def process_document_async(document_id: str) -> dict:
514
+ """Complete document processing with chunking and embeddings."""
515
+ try:
516
+ document = Document.objects.get(id=document_id)
517
+
518
+ # Step 1: Chunk document
519
+ chunks = create_document_chunks(document)
520
+
521
+ # Step 2: Generate embeddings
522
+ for chunk in chunks:
523
+ generate_embeddings.send(chunk.id)
524
+
525
+ # Step 3: Optimize database
526
+ optimize_document_embeddings.send(document_id)
527
+
528
+ return {"status": "completed", "chunks_created": len(chunks)}
529
+
530
+ except Exception as e:
531
+ logger.error(f"Document processing failed: {e}")
532
+ return {"status": "failed", "error": str(e)}
533
+
534
+ # Triggered automatically via Django signals
535
+ @receiver(post_save, sender=Document)
536
+ def queue_document_processing(sender, instance, created, **kwargs):
537
+ if created:
538
+ process_document_async.send(str(instance.id))
539
+ ```
540
+
541
+ **Perfect for:**
542
+ - 📄 **Document Processing** - PDF parsing, text extraction, embeddings
543
+ - 📧 **Email Campaigns** - Bulk email sending with delivery tracking
544
+ - 🔄 **Data Synchronization** - API integrations and data imports
545
+ - 📊 **Report Generation** - Heavy computational tasks
546
+ - 🧹 **Cleanup Tasks** - Database maintenance and optimization
418
547
 
419
548
  ---
420
549
 
@@ -444,6 +573,7 @@ Django-CFG includes powerful management commands for development and operations:
444
573
  | **`rundramatiq`** | Run Dramatiq background task workers | `python manage.py rundramatiq --processes 4` |
445
574
  | **`task_status`** | Show Dramatiq task status and queues | `python manage.py task_status --queue high` |
446
575
  | **`task_clear`** | Clear Dramatiq queues | `python manage.py task_clear --queue default` |
576
+ | **`test_tasks`** | Test Dramatiq task processing pipeline | `python manage.py test_tasks --document-id 123` |
447
577
  | **`tree`** | Display Django project structure | `python manage.py tree --depth 3 --include-docs` |
448
578
  | **`validate_config`** | Deep validation of all settings | `python manage.py validate_config --strict` |
449
579
 
@@ -955,6 +1085,17 @@ class ProductionConfig(DjangoConfig):
955
1085
  enable_newsletter: bool = True # Email marketing, campaigns, tracking & analytics
956
1086
  enable_leads: bool = True # Lead capture, CRM integration, source tracking
957
1087
 
1088
+ # === Background Task Processing ===
1089
+ redis_url: str = "redis://redis:6379/2" # Separate DB for Dramatiq tasks
1090
+ dramatiq: DramatiqConfig = DramatiqConfig(
1091
+ processes=4, # Production worker processes
1092
+ threads=8, # Threads per process for I/O bound tasks
1093
+ redis_db=2, # Dedicated Redis DB for task queues
1094
+ queues=["default", "high", "low", "knowledge", "email"], # Production queues
1095
+ max_retries=3, # Default retry attempts
1096
+ max_age=3600000, # 1 hour max task age (milliseconds)
1097
+ )
1098
+
958
1099
  # === Multi-Zone API ===
959
1100
  revolution: RevolutionConfig = RevolutionConfig(
960
1101
  api_prefix="api/v2",
@@ -47,7 +47,7 @@ python manage.py runserver
47
47
  - ✅ **Newsletter campaigns** with email tracking
48
48
  - ✅ **Lead management** system with CRM integration
49
49
  - ✅ **Multi-database routing** and connection pooling
50
- - ✅ **Background task processing** with Dramatiq
50
+ - ✅ **Background task processing** with production-ready Dramatiq integration
51
51
  - ✅ **Webhook testing** with built-in ngrok integration
52
52
  - ✅ **Type-safe configuration** with full IDE support
53
53
 
@@ -287,8 +287,137 @@ Automatic dev/staging/production detection with appropriate defaults.
287
287
  ### 🌐 **Built-in Ngrok Integration**
288
288
  Instant webhook testing with zero-config ngrok tunnels for development.
289
289
 
290
- ### 🔄 **Background Task Processing**
291
- Built-in Dramatiq integration for reliable background job processing with Redis.
290
+ ### 🔄 **Background Task Processing** %%PRIORITY:HIGH%%
291
+
292
+ Django-CFG includes a complete Dramatiq integration for reliable background job processing with automatic Redis configuration, worker management, and task monitoring.
293
+
294
+ #### Features
295
+ - **🚀 Zero Configuration** - Automatic Redis broker setup and queue management
296
+ - **⚡ Smart Worker Management** - Built-in `rundramatiq` command with Django settings integration
297
+ - **🔧 Type-Safe Task Definition** - Full IDE support for task creation and scheduling
298
+ - **📊 Task Monitoring** - Built-in commands for queue status and task management
299
+ - **🐳 Docker Ready** - Pre-configured Docker containers for production deployment
300
+ - **🛡️ Production Tested** - Battle-tested configuration used in production environments
301
+
302
+ #### Quick Setup
303
+ ```python
304
+ from django_cfg import DjangoConfig
305
+
306
+ class MyConfig(DjangoConfig):
307
+ project_name: str = "My App"
308
+
309
+ # Dramatiq configuration (automatic)
310
+ redis_url: str = "redis://localhost:6379/2" # Separate DB for tasks
311
+
312
+ # Optional: Custom task settings
313
+ dramatiq: DramatiqConfig = DramatiqConfig(
314
+ processes=2, # Worker processes
315
+ threads=4, # Threads per process
316
+ redis_db=2, # Redis database for tasks
317
+ queues=["default", "high", "low"] # Available queues
318
+ )
319
+
320
+ config = MyConfig()
321
+ ```
322
+
323
+ #### Task Definition
324
+ ```python
325
+ import dramatiq
326
+ from django_cfg.modules.django_tasks import get_broker
327
+
328
+ # Tasks are automatically discovered from your apps
329
+ @dramatiq.actor(queue_name="high", max_retries=3)
330
+ def process_document(document_id: str) -> dict:
331
+ """Process document asynchronously with full Django context."""
332
+ from myapp.models import Document
333
+
334
+ document = Document.objects.get(id=document_id)
335
+ # Your processing logic here
336
+ document.status = "processed"
337
+ document.save()
338
+
339
+ return {"status": "completed", "document_id": document_id}
340
+
341
+ # Queue the task
342
+ process_document.send(document_id="123")
343
+ ```
344
+
345
+ #### Management Commands
346
+ ```bash
347
+ # Start Dramatiq workers with Django settings
348
+ python manage.py rundramatiq --processes 4 --threads 8
349
+
350
+ # Monitor task queues and status
351
+ python manage.py task_status --queue high
352
+
353
+ # Clear specific queues
354
+ python manage.py task_clear --queue default
355
+
356
+ # Test task processing pipeline
357
+ python manage.py test_tasks
358
+ ```
359
+
360
+ #### Docker Integration
361
+ ```yaml
362
+ # docker-compose.yml (automatically generated)
363
+ services:
364
+ app-dramatiq:
365
+ build: .
366
+ command: ["python", "manage.py", "rundramatiq"]
367
+ environment:
368
+ - DRAMATIQ_PROCESSES=2
369
+ - DRAMATIQ_THREADS=4
370
+ - DRAMATIQ_QUEUES=default,high,low
371
+ depends_on:
372
+ - redis
373
+ - postgres
374
+ ```
375
+
376
+ #### Production Features
377
+ - **🔄 Automatic Restart** - Workers restart on code changes in development
378
+ - **📈 Scaling** - Easy horizontal scaling with multiple worker containers
379
+ - **🛡️ Error Handling** - Built-in retry logic and dead letter queues
380
+ - **📊 Monitoring** - Integration with Django admin for task monitoring
381
+ - **⚡ Performance** - Optimized Redis configuration for high throughput
382
+
383
+ #### Real-World Example
384
+ ```python
385
+ # Document processing pipeline
386
+ @dramatiq.actor(queue_name="knowledge", max_retries=2)
387
+ def process_document_async(document_id: str) -> dict:
388
+ """Complete document processing with chunking and embeddings."""
389
+ try:
390
+ document = Document.objects.get(id=document_id)
391
+
392
+ # Step 1: Chunk document
393
+ chunks = create_document_chunks(document)
394
+
395
+ # Step 2: Generate embeddings
396
+ for chunk in chunks:
397
+ generate_embeddings.send(chunk.id)
398
+
399
+ # Step 3: Optimize database
400
+ optimize_document_embeddings.send(document_id)
401
+
402
+ return {"status": "completed", "chunks_created": len(chunks)}
403
+
404
+ except Exception as e:
405
+ logger.error(f"Document processing failed: {e}")
406
+ return {"status": "failed", "error": str(e)}
407
+
408
+ # Triggered automatically via Django signals
409
+ @receiver(post_save, sender=Document)
410
+ def queue_document_processing(sender, instance, created, **kwargs):
411
+ if created:
412
+ process_document_async.send(str(instance.id))
413
+ ```
414
+
415
+ **Perfect for:**
416
+ - 📄 **Document Processing** - PDF parsing, text extraction, embeddings
417
+ - 📧 **Email Campaigns** - Bulk email sending with delivery tracking
418
+ - 🔄 **Data Synchronization** - API integrations and data imports
419
+ - 📊 **Report Generation** - Heavy computational tasks
420
+ - 🧹 **Cleanup Tasks** - Database maintenance and optimization
292
421
 
293
422
  ---
294
423
 
@@ -318,6 +447,7 @@ Django-CFG includes powerful management commands for development and operations:
318
447
  | **`rundramatiq`** | Run Dramatiq background task workers | `python manage.py rundramatiq --processes 4` |
319
448
  | **`task_status`** | Show Dramatiq task status and queues | `python manage.py task_status --queue high` |
320
449
  | **`task_clear`** | Clear Dramatiq queues | `python manage.py task_clear --queue default` |
450
+ | **`test_tasks`** | Test Dramatiq task processing pipeline | `python manage.py test_tasks --document-id 123` |
321
451
  | **`tree`** | Display Django project structure | `python manage.py tree --depth 3 --include-docs` |
322
452
  | **`validate_config`** | Deep validation of all settings | `python manage.py validate_config --strict` |
323
453
 
@@ -829,6 +959,17 @@ class ProductionConfig(DjangoConfig):
829
959
  enable_newsletter: bool = True # Email marketing, campaigns, tracking & analytics
830
960
  enable_leads: bool = True # Lead capture, CRM integration, source tracking
831
961
 
962
+ # === Background Task Processing ===
963
+ redis_url: str = "redis://redis:6379/2" # Separate DB for Dramatiq tasks
964
+ dramatiq: DramatiqConfig = DramatiqConfig(
965
+ processes=4, # Production worker processes
966
+ threads=8, # Threads per process for I/O bound tasks
967
+ redis_db=2, # Dedicated Redis DB for task queues
968
+ queues=["default", "high", "low", "knowledge", "email"], # Production queues
969
+ max_retries=3, # Default retry attempts
970
+ max_age=3600000, # 1 hour max task age (milliseconds)
971
+ )
972
+
832
973
  # === Multi-Zone API ===
833
974
  revolution: RevolutionConfig = RevolutionConfig(
834
975
  api_prefix="api/v2",
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "django-cfg"
7
- version = "1.1.61"
7
+ version = "1.1.63"
8
8
  description = "🚀 Production-ready Django configuration framework with type-safe settings, smart automation, and modern developer experience"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -38,7 +38,7 @@ default_app_config = "django_cfg.apps.DjangoCfgConfig"
38
38
  from typing import TYPE_CHECKING
39
39
 
40
40
  # Version information
41
- __version__ = "1.1.60"
41
+ __version__ = "1.1.63"
42
42
  __author__ = "Unrealos Team"
43
43
  __email__ = "info@unrealos.com"
44
44
  __license__ = "MIT"
@@ -0,0 +1,241 @@
1
+ """
2
+ Django management command for running Dramatiq workers.
3
+
4
+ Based on django_dramatiq.management.commands.rundramatiq with Django-CFG integration.
5
+ Simple, clean, and working approach.
6
+ """
7
+
8
+ import argparse
9
+ import importlib
10
+ import multiprocessing
11
+ import os
12
+ import sys
13
+
14
+ from django.apps import apps
15
+ from django.conf import settings
16
+ from django.core.management.base import BaseCommand
17
+ from django.utils.module_loading import module_has_submodule
18
+
19
+ from django_cfg.modules.django_tasks import get_task_service
20
+
21
+
22
+ # Default values
23
+ NPROCS = multiprocessing.cpu_count()
24
+ NTHREADS = 8
25
+
26
+
27
+ class Command(BaseCommand):
28
+ help = "Run Dramatiq workers with Django-CFG configuration."
29
+
30
+ def add_arguments(self, parser):
31
+ parser.formatter_class = argparse.ArgumentDefaultsHelpFormatter
32
+
33
+ parser.add_argument(
34
+ "--processes", "-p",
35
+ default=NPROCS,
36
+ type=int,
37
+ help="The number of processes to run",
38
+ )
39
+ parser.add_argument(
40
+ "--threads", "-t",
41
+ default=NTHREADS,
42
+ type=int,
43
+ help="The number of threads per process to use",
44
+ )
45
+ parser.add_argument(
46
+ "--queues", "-Q",
47
+ nargs="*",
48
+ type=str,
49
+ help="Listen to a subset of queues, or all when empty",
50
+ )
51
+ parser.add_argument(
52
+ "--watch",
53
+ dest="watch_dir",
54
+ help="Reload workers when changes are detected in the given directory",
55
+ )
56
+ parser.add_argument(
57
+ "--pid-file",
58
+ type=str,
59
+ help="Write the PID of the master process to this file",
60
+ )
61
+ parser.add_argument(
62
+ "--log-file",
63
+ type=str,
64
+ help="Write all logs to a file, or stderr when empty",
65
+ )
66
+ parser.add_argument(
67
+ "--worker-shutdown-timeout",
68
+ type=int,
69
+ default=600000,
70
+ help="Timeout for worker shutdown, in milliseconds"
71
+ )
72
+ parser.add_argument(
73
+ "--dry-run",
74
+ action="store_true",
75
+ help="Show configuration without starting workers",
76
+ )
77
+
78
+ def handle(self, watch_dir, processes, threads, verbosity, queues,
79
+ pid_file, log_file, worker_shutdown_timeout, dry_run, **options):
80
+
81
+ # Get task service and validate
82
+ task_service = get_task_service()
83
+ if not task_service.is_enabled():
84
+ self.stdout.write(
85
+ self.style.ERROR("Task system is not enabled in Django-CFG configuration")
86
+ )
87
+ return
88
+
89
+ # Discover task modules
90
+ tasks_modules = self._discover_tasks_modules()
91
+
92
+ # Show configuration info
93
+ self.stdout.write(self.style.SUCCESS("Dramatiq Worker Configuration:"))
94
+ self.stdout.write(f"Processes: {processes}")
95
+ self.stdout.write(f"Threads: {threads}")
96
+ if queues:
97
+ self.stdout.write(f"Queues: {', '.join(queues)}")
98
+ else:
99
+ self.stdout.write("Queues: all")
100
+
101
+ self.stdout.write(f"\nDiscovered task modules:")
102
+ for module in tasks_modules:
103
+ self.stdout.write(f" - {module}")
104
+
105
+ # If dry run, show command and exit
106
+ if dry_run:
107
+ executable_name = "dramatiq"
108
+ process_args = [
109
+ executable_name,
110
+ "--processes", str(processes),
111
+ "--threads", str(threads),
112
+ "--worker-shutdown-timeout", str(worker_shutdown_timeout),
113
+ ]
114
+
115
+ if watch_dir:
116
+ process_args.extend(["--watch", watch_dir])
117
+
118
+ verbosity_args = ["-v"] * (verbosity - 1)
119
+ process_args.extend(verbosity_args)
120
+
121
+ if queues:
122
+ process_args.extend(["--queues", *queues])
123
+
124
+ if pid_file:
125
+ process_args.extend(["--pid-file", pid_file])
126
+
127
+ if log_file:
128
+ process_args.extend(["--log-file", log_file])
129
+
130
+ process_args.extend(tasks_modules)
131
+
132
+ self.stdout.write(f"\nCommand that would be executed:")
133
+ self.stdout.write(f' {" ".join(process_args)}')
134
+ return
135
+
136
+ # Show startup info
137
+ self.stdout.write(self.style.SUCCESS("\nStarting Dramatiq workers..."))
138
+
139
+ # Build dramatiq command
140
+ executable_name = "dramatiq"
141
+ executable_path = self._resolve_executable(executable_name)
142
+
143
+ # Build process arguments exactly like django_dramatiq
144
+ process_args = [
145
+ executable_name,
146
+ "--processes", str(processes),
147
+ "--threads", str(threads),
148
+ "--worker-shutdown-timeout", str(worker_shutdown_timeout),
149
+ ]
150
+
151
+ # Add watch directory if specified
152
+ if watch_dir:
153
+ process_args.extend(["--watch", watch_dir])
154
+
155
+ # Add verbosity
156
+ verbosity_args = ["-v"] * (verbosity - 1)
157
+ process_args.extend(verbosity_args)
158
+
159
+ # Add queues if specified
160
+ if queues:
161
+ process_args.extend(["--queues", *queues])
162
+
163
+ # Add PID file if specified
164
+ if pid_file:
165
+ process_args.extend(["--pid-file", pid_file])
166
+
167
+ # Add log file if specified
168
+ if log_file:
169
+ process_args.extend(["--log-file", log_file])
170
+
171
+ # Add task modules (broker module first, then discovered modules)
172
+ process_args.extend(tasks_modules)
173
+
174
+ self.stdout.write(f'Running dramatiq: "{" ".join(process_args)}"\n')
175
+
176
+ # Ensure DJANGO_SETTINGS_MODULE is set for worker processes
177
+ if not os.environ.get('DJANGO_SETTINGS_MODULE'):
178
+ if hasattr(settings, 'SETTINGS_MODULE'):
179
+ os.environ['DJANGO_SETTINGS_MODULE'] = settings.SETTINGS_MODULE
180
+ else:
181
+ # Try to detect from manage.py or current settings
182
+ import django
183
+ from django.conf import settings as django_settings
184
+ if hasattr(django_settings, '_wrapped') and hasattr(django_settings._wrapped, '__module__'):
185
+ module_name = django_settings._wrapped.__module__
186
+ os.environ['DJANGO_SETTINGS_MODULE'] = module_name
187
+ else:
188
+ self.stdout.write(
189
+ self.style.WARNING("Could not detect DJANGO_SETTINGS_MODULE")
190
+ )
191
+
192
+ # Use os.execvp like django_dramatiq to preserve environment
193
+ if sys.platform == "win32":
194
+ import subprocess
195
+ command = [executable_path] + process_args[1:]
196
+ sys.exit(subprocess.run(command))
197
+
198
+ os.execvp(executable_path, process_args)
199
+
200
+ def _discover_tasks_modules(self):
201
+ """Discover task modules like django_dramatiq does."""
202
+ # Always include our broker setup module first
203
+ tasks_modules = ["django_cfg.modules.dramatiq_setup"]
204
+
205
+ # Get task service for configuration
206
+ task_service = get_task_service()
207
+
208
+ # Try to get task modules from Django-CFG config
209
+ if task_service.config and task_service.config.auto_discover_tasks:
210
+ discovered = task_service.discover_tasks()
211
+ for module_name in discovered:
212
+ self.stdout.write(f"Discovered tasks module: '{module_name}'")
213
+ tasks_modules.append(module_name)
214
+
215
+ # Fallback: use django_dramatiq discovery logic
216
+ if len(tasks_modules) == 1: # Only broker module found
217
+ task_module_names = getattr(settings, "DRAMATIQ_AUTODISCOVER_MODULES", ("tasks",))
218
+
219
+ for app_config in apps.get_app_configs():
220
+ for task_module in task_module_names:
221
+ if module_has_submodule(app_config.module, task_module):
222
+ module_name = f"{app_config.name}.{task_module}"
223
+ try:
224
+ importlib.import_module(module_name)
225
+ self.stdout.write(f"Discovered tasks module: '{module_name}'")
226
+ tasks_modules.append(module_name)
227
+ except ImportError:
228
+ # Module exists but has import errors, skip it
229
+ pass
230
+
231
+ return tasks_modules
232
+
233
+ def _resolve_executable(self, exec_name):
234
+ """Resolve executable path like django_dramatiq does."""
235
+ bin_dir = os.path.dirname(sys.executable)
236
+ if bin_dir:
237
+ for d in [bin_dir, os.path.join(bin_dir, "Scripts")]:
238
+ exec_path = os.path.join(d, exec_name)
239
+ if os.path.isfile(exec_path):
240
+ return exec_path
241
+ return exec_name