django-cfg 1.4.113__py3-none-any.whl → 1.4.114__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.

Potentially problematic release.


This version of django-cfg might be problematic. Click here for more details.

Files changed (32) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/apps/dashboard/serializers/__init__.py +10 -8
  3. django_cfg/apps/dashboard/serializers/django_q2.py +50 -0
  4. django_cfg/apps/dashboard/services/__init__.py +2 -2
  5. django_cfg/apps/dashboard/services/django_q2_service.py +159 -0
  6. django_cfg/apps/dashboard/services/system_health_service.py +39 -26
  7. django_cfg/apps/dashboard/urls.py +2 -2
  8. django_cfg/apps/dashboard/views/__init__.py +2 -2
  9. django_cfg/apps/dashboard/views/django_q2_views.py +79 -0
  10. django_cfg/apps/tasks/migrations/0002_delete_tasklog.py +16 -0
  11. django_cfg/core/base/config_model.py +15 -5
  12. django_cfg/core/builders/apps_builder.py +3 -3
  13. django_cfg/core/generation/data_generators/cache.py +28 -2
  14. django_cfg/core/generation/integration_generators/__init__.py +4 -3
  15. django_cfg/core/generation/integration_generators/django_q2.py +133 -0
  16. django_cfg/core/generation/orchestrator.py +7 -7
  17. django_cfg/models/__init__.py +3 -3
  18. django_cfg/models/django/__init__.py +3 -3
  19. django_cfg/models/django/django_q2.py +491 -0
  20. django_cfg/pyproject.toml +2 -2
  21. django_cfg/registry/core.py +3 -3
  22. django_cfg/static/frontend/admin.zip +0 -0
  23. {django_cfg-1.4.113.dist-info → django_cfg-1.4.114.dist-info}/METADATA +3 -2
  24. {django_cfg-1.4.113.dist-info → django_cfg-1.4.114.dist-info}/RECORD +27 -26
  25. django_cfg/apps/dashboard/serializers/crontab.py +0 -84
  26. django_cfg/apps/dashboard/services/crontab_service.py +0 -210
  27. django_cfg/apps/dashboard/views/crontab_views.py +0 -72
  28. django_cfg/core/generation/integration_generators/crontab.py +0 -64
  29. django_cfg/models/django/crontab.py +0 -303
  30. {django_cfg-1.4.113.dist-info → django_cfg-1.4.114.dist-info}/WHEEL +0 -0
  31. {django_cfg-1.4.113.dist-info → django_cfg-1.4.114.dist-info}/entry_points.txt +0 -0
  32. {django_cfg-1.4.113.dist-info → django_cfg-1.4.114.dist-info}/licenses/LICENSE +0 -0
django_cfg/pyproject.toml CHANGED
@@ -4,13 +4,13 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "django-cfg"
7
- version = "1.4.113"
7
+ version = "1.4.114"
8
8
  description = "Modern Django framework with type-safe Pydantic v2 configuration, Next.js admin integration, real-time WebSockets, and 8 enterprise apps. Replace settings.py with validated models, 90% less code. Production-ready with AI agents, auto-generated TypeScript clients, and zero-config features."
9
9
  readme = "README.md"
10
10
  keywords = [ "django", "configuration", "pydantic", "settings", "type-safety", "pydantic-settings", "django-environ", "startup-validation", "ide-autocomplete", "nextjs-admin", "react-admin", "websocket", "centrifugo", "real-time", "typescript-generation", "ai-agents", "enterprise-django", "django-settings", "type-safe-config", "modern-django",]
11
11
  classifiers = [ "Development Status :: 4 - Beta", "Framework :: Django", "Framework :: Django :: 5.2", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: Dynamic Content", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: System :: Systems Administration", "Typing :: Typed",]
12
12
  requires-python = ">=3.12,<3.14"
13
- dependencies = [ "pydantic>=2.11.0,<3.0", "pydantic[email]>=2.11.0,<3.0", "PyYAML>=6.0,<7.0", "click>=8.2.0,<9.0", "questionary>=2.1.0,<3.0", "rich>=14.0.0,<15.0", "cloudflare>=4.3.0,<5.0", "loguru>=0.7.0,<1.0", "colorlog>=6.9.0,<7.0", "cachetools>=5.3.0,<7.0", "toml>=0.10.2,<0.11.0", "ngrok>=1.5.1; python_version>='3.12'", "psycopg[binary,pool]>=3.2.0,<4.0", "dj-database-url>=3.0.0,<4.0", "whitenoise>=6.8.0,<7.0", "django-cors-headers>=4.7.0,<5.0", "django-crontab>=0.7.1,<1.0", "djangorestframework>=3.16.0,<4.0", "djangorestframework-simplejwt>=5.5.0,<6.0", "djangorestframework-simplejwt[token-blacklist]>=5.5.0,<6.0", "drf-nested-routers>=0.94.0,<1.0", "django-filter>=25.0,<26.0", "django-ratelimit>=4.1.0,<5.0.0", "drf-spectacular>=0.28.0,<1.0", "drf-spectacular-sidecar>=2025.8.0,<2026.0", "django-json-widget>=2.0.0,<3.0", "django-import-export>=4.3.0,<5.0", "django-extensions>=4.1.0,<5.0", "django-constance>=4.3.0,<5.0", "django-unfold>=0.64.0,<1.0", "django-redis>=6.0.0,<7.0", "redis>=6.4.0,<7.0", "hiredis>=2.0.0,<4.0", "rearq>=0.2.0,<1.0", "setuptools>=75.0.0; python_version>='3.13'", "pyTelegramBotAPI>=4.28.0,<5.0", "coolname>=2.2.0,<3.0", "django-admin-rangefilter>=0.13.0,<1.0", "python-json-logger>=3.3.0,<4.0", "requests>=2.32.0,<3.0", "tiktoken>=0.11.0,<1.0", "openai>=1.107.0,<2.0", "twilio>=9.8.0,<10.0", "sendgrid>=6.12.0,<7.0", "beautifulsoup4>=4.13.0,<5.0", "lxml>=6.0.0,<7.0", "pgvector>=0.4.0,<1.0", "tenacity>=9.1.2,<10.0.0", "mypy (>=1.18.2,<2.0.0)", "django-tailwind[reload] (>=4.2.0,<5.0.0)", "jinja2 (>=3.1.6,<4.0.0)", "django-axes[ipware] (>=8.0.0,<9.0.0)", "pydantic-settings (>=2.11.0,<3.0.0)", "pytz>=2025.1", "httpx>=0.28.1,<1.0", "mistune>=3.1.4,<4.0",]
13
+ dependencies = [ "pydantic>=2.11.0,<3.0", "pydantic[email]>=2.11.0,<3.0", "PyYAML>=6.0,<7.0", "click>=8.2.0,<9.0", "questionary>=2.1.0,<3.0", "rich>=14.0.0,<15.0", "cloudflare>=4.3.0,<5.0", "loguru>=0.7.0,<1.0", "colorlog>=6.9.0,<7.0", "cachetools>=5.3.0,<7.0", "toml>=0.10.2,<0.11.0", "ngrok>=1.5.1; python_version>='3.12'", "psycopg[binary,pool]>=3.2.0,<4.0", "dj-database-url>=3.0.0,<4.0", "whitenoise>=6.8.0,<7.0", "django-cors-headers>=4.7.0,<5.0", "django-q2==1.8.0", "croniter>=6.0.0,<7.0", "djangorestframework>=3.16.0,<4.0", "djangorestframework-simplejwt>=5.5.0,<6.0", "djangorestframework-simplejwt[token-blacklist]>=5.5.0,<6.0", "drf-nested-routers>=0.94.0,<1.0", "django-filter>=25.0,<26.0", "django-ratelimit>=4.1.0,<5.0.0", "drf-spectacular>=0.28.0,<1.0", "drf-spectacular-sidecar>=2025.8.0,<2026.0", "django-json-widget>=2.0.0,<3.0", "django-import-export>=4.3.0,<5.0", "django-extensions>=4.1.0,<5.0", "django-constance>=4.3.0,<5.0", "django-unfold>=0.64.0,<1.0", "django-redis>=6.0.0,<7.0", "redis>=6.4.0,<7.0", "hiredis>=2.0.0,<4.0", "rearq>=0.2.0,<1.0", "setuptools>=75.0.0; python_version>='3.13'", "pyTelegramBotAPI>=4.28.0,<5.0", "coolname>=2.2.0,<3.0", "django-admin-rangefilter>=0.13.0,<1.0", "python-json-logger>=3.3.0,<4.0", "requests>=2.32.0,<3.0", "tiktoken>=0.11.0,<1.0", "openai>=1.107.0,<2.0", "twilio>=9.8.0,<10.0", "sendgrid>=6.12.0,<7.0", "beautifulsoup4>=4.13.0,<5.0", "lxml>=6.0.0,<7.0", "pgvector>=0.4.0,<1.0", "tenacity>=9.1.2,<10.0.0", "mypy (>=1.18.2,<2.0.0)", "django-tailwind[reload] (>=4.2.0,<5.0.0)", "jinja2 (>=3.1.6,<4.0.0)", "django-axes[ipware] (>=8.0.0,<9.0.0)", "pydantic-settings (>=2.11.0,<3.0.0)", "pytz>=2025.1", "httpx>=0.28.1,<1.0", "mistune>=3.1.4,<4.0",]
14
14
  [[project.authors]]
15
15
  name = "Django-CFG Team"
16
16
  email = "info@djangocfg.com"
@@ -38,9 +38,9 @@ CORE_REGISTRY = {
38
38
  # Security - Django Crypto Fields
39
39
  "CryptoFieldsConfig": ("django_cfg.models.django.crypto_fields", "CryptoFieldsConfig"),
40
40
 
41
- # Scheduling - Django Crontab
42
- "CrontabConfig": ("django_cfg.models.django.crontab", "CrontabConfig"),
43
- "CrontabJobConfig": ("django_cfg.models.django.crontab", "CrontabJobConfig"),
41
+ # Scheduling - Django-Q2
42
+ "DjangoQ2Config": ("django_cfg.models.django.django_q2", "DjangoQ2Config"),
43
+ "DjangoQ2ScheduleConfig": ("django_cfg.models.django.django_q2", "DjangoQ2ScheduleConfig"),
44
44
 
45
45
  # Limits models
46
46
  "LimitsConfig": ("django_cfg.models.api.limits", "LimitsConfig"),
Binary file
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-cfg
3
- Version: 1.4.113
3
+ Version: 1.4.114
4
4
  Summary: Modern Django framework with type-safe Pydantic v2 configuration, Next.js admin integration, real-time WebSockets, and 8 enterprise apps. Replace settings.py with validated models, 90% less code. Production-ready with AI agents, auto-generated TypeScript clients, and zero-config features.
5
5
  Project-URL: Homepage, https://djangocfg.com
6
6
  Project-URL: Documentation, https://djangocfg.com
@@ -34,16 +34,17 @@ Requires-Dist: click<9.0,>=8.2.0
34
34
  Requires-Dist: cloudflare<5.0,>=4.3.0
35
35
  Requires-Dist: colorlog<7.0,>=6.9.0
36
36
  Requires-Dist: coolname<3.0,>=2.2.0
37
+ Requires-Dist: croniter<7.0,>=6.0.0
37
38
  Requires-Dist: dj-database-url<4.0,>=3.0.0
38
39
  Requires-Dist: django-admin-rangefilter<1.0,>=0.13.0
39
40
  Requires-Dist: django-axes[ipware]<9.0.0,>=8.0.0
40
41
  Requires-Dist: django-constance<5.0,>=4.3.0
41
42
  Requires-Dist: django-cors-headers<5.0,>=4.7.0
42
- Requires-Dist: django-crontab<1.0,>=0.7.1
43
43
  Requires-Dist: django-extensions<5.0,>=4.1.0
44
44
  Requires-Dist: django-filter<26.0,>=25.0
45
45
  Requires-Dist: django-import-export<5.0,>=4.3.0
46
46
  Requires-Dist: django-json-widget<3.0,>=2.0.0
47
+ Requires-Dist: django-q2==1.8.0
47
48
  Requires-Dist: django-ratelimit<5.0.0,>=4.1.0
48
49
  Requires-Dist: django-redis<7.0,>=6.0.0
49
50
  Requires-Dist: django-tailwind[reload]<5.0.0,>=4.2.0
@@ -1,5 +1,5 @@
1
1
  django_cfg/README.md,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- django_cfg/__init__.py,sha256=YGTIO_6MaFs7LomBGxf6vfZ3CUo627p3WtaDSgJUa6o,1621
2
+ django_cfg/__init__.py,sha256=MWuXwRHUZtVt1_3qryh_271FF5bBx2dxkXP91uVtiok,1621
3
3
  django_cfg/apps.py,sha256=72m3uuvyqGiLx6gOfE-BD3P61jddCCERuBOYpxTX518,1605
4
4
  django_cfg/config.py,sha256=xdwFE8bocOEnMjqDOwr1_M02oUgdaMG_2M6F_IuB9GQ,1351
5
5
  django_cfg/apps/__init__.py,sha256=JtDmEYt1OcleWM2ZaeX0LKDnRQzPOavfaXBWG4ECB5Q,26
@@ -196,32 +196,32 @@ django_cfg/apps/centrifugo/views/testing_api.py,sha256=sNBmYoRD7VBXZmoHEw9BmPbDa
196
196
  django_cfg/apps/dashboard/__init__.py,sha256=TirqQji7p39fA15jGBswWSt6ML2K1SP96Iq-7Sw7NFI,236
197
197
  django_cfg/apps/dashboard/apps.py,sha256=OvB_C5qTq-QcLvvrRpbBxJPL-DCtA-pGVK8ir2y-hKk,508
198
198
  django_cfg/apps/dashboard/permissions.py,sha256=LJGza0pjVfoR2rQjKYZWnkgGcyzSHr43RMYiCibrokQ,1360
199
- django_cfg/apps/dashboard/urls.py,sha256=gpoaBnWWmeXRzvBtxVZ-nAdWhOuJu2D-V2GvMcNnieU,1345
200
- django_cfg/apps/dashboard/serializers/__init__.py,sha256=famL6jk8sDLYt4G2JZZd6hPlpHk-DRiYjviUMd_0WaU,1753
199
+ django_cfg/apps/dashboard/urls.py,sha256=4LYRy8AOVHD4e-E8K_KW4-nFpH21g-yEjYdL13Evr_E,1351
200
+ django_cfg/apps/dashboard/serializers/__init__.py,sha256=QB31m7FxYlm1TEMp1zMvm6QgXaMGbI7PwlPgfcZzlrs,1837
201
201
  django_cfg/apps/dashboard/serializers/activity.py,sha256=eaimk1eI1-WPFa_b8oqF-xM5V6uoSBlS0mRR7TfMtrQ,1410
202
202
  django_cfg/apps/dashboard/serializers/apizones.py,sha256=eeluzYPtrSXskpfFY2ykw3yM71BCr5_XoAomcU-zNqE,773
203
203
  django_cfg/apps/dashboard/serializers/base.py,sha256=-PRmxV3eApf-JfFVjgiL8ka0b07m69crkIECX-EK4IY,526
204
204
  django_cfg/apps/dashboard/serializers/charts.py,sha256=EPgIcQ2jPLp2-5IbVWyhP86p_puPU0TMxitFR3yPfDE,1425
205
205
  django_cfg/apps/dashboard/serializers/commands.py,sha256=qiRcSMNz7J72TcSVZLYD-oZxEAN3hmt_MZx9kkxlp7o,1925
206
- django_cfg/apps/dashboard/serializers/crontab.py,sha256=gMP7eWt5sSwIWjYozeDcPMKkU_UU5jFS8oljE5hDnU0,3043
206
+ django_cfg/apps/dashboard/serializers/django_q2.py,sha256=sSCxaP_xwwNlY58lI6LooJ6JwHeaUwltXZkX2wtvloM,1735
207
207
  django_cfg/apps/dashboard/serializers/overview.py,sha256=ejFZV2l2GOTHLA8XQty8SayyXM-cL3VM2veY7YoMeWE,1373
208
208
  django_cfg/apps/dashboard/serializers/statistics.py,sha256=DrT3eDdsqSaeCE3GJ_7_o5Tl_WVc2NwNJ43fm-kPu2A,1664
209
209
  django_cfg/apps/dashboard/serializers/system.py,sha256=mDwqPVS2iBfyCcs4BcnT2_kZWRnbWCtLvoTievc7qkU,2093
210
- django_cfg/apps/dashboard/services/__init__.py,sha256=zunW2R4GRa8ffumFo9KVY1xUEH4Dg2AeO63DRA4nQ2I,683
210
+ django_cfg/apps/dashboard/services/__init__.py,sha256=nDMZcwG036iLta9LsAGQ39W8NfvDC8vt6j8xlBLaQ2A,687
211
211
  django_cfg/apps/dashboard/services/apizones_service.py,sha256=FVpdMgBzjTzK3G5zZb2ADKL8ZrjEmdclCRNOr4AdIGI,3955
212
212
  django_cfg/apps/dashboard/services/charts_service.py,sha256=QP4nWghSvkqTX-9ndQmmzdEDIsxVewGZj8Oy27kLoOA,8848
213
213
  django_cfg/apps/dashboard/services/commands_security.py,sha256=kFADVoYNbqb2DwzFfFBZ3Th2TdfL-1z2V-dnNXHU5Fw,7893
214
214
  django_cfg/apps/dashboard/services/commands_service.py,sha256=OnvZBUv2GDUWq3JA3UVrHu-gMc2eJm0-MT_WTdM27uk,11644
215
- django_cfg/apps/dashboard/services/crontab_service.py,sha256=MWIU5PsqoioolY4TFlSrYmcSak-RAaxuOZLewhNl3BU,6461
215
+ django_cfg/apps/dashboard/services/django_q2_service.py,sha256=BalFPJhEDWPYv1fugYe123GQOSh0Gpdt6imJkNyQA1w,5113
216
216
  django_cfg/apps/dashboard/services/overview_service.py,sha256=Dl_y89_waG9onDC9PHGWx0ci7m3NOdrMoEKSdv3Fves,6382
217
217
  django_cfg/apps/dashboard/services/statistics_service.py,sha256=cX20DB0VrjDLaaLCp8YQUcBw_N34VzZKqY4Ly2Qal0M,14023
218
- django_cfg/apps/dashboard/services/system_health_service.py,sha256=PI7OdMIHMhyxfhZ2PiyxMwgRVaH9PdDGVKRDmmxqbQo,12071
219
- django_cfg/apps/dashboard/views/__init__.py,sha256=Bdvv-zj5vXPsqoIk7q8KH9eFN7kS55g9IYmpgrZPpj0,625
218
+ django_cfg/apps/dashboard/services/system_health_service.py,sha256=oekgJva1T-WTMqrNnlKRvaVbJvPI2PtSfUAe4coGNlg,12695
219
+ django_cfg/apps/dashboard/views/__init__.py,sha256=caP9Gt_4e_1kORhRLmWd2TJbIMbf86peKSXnf6ltFwE,629
220
220
  django_cfg/apps/dashboard/views/activity_views.py,sha256=UsGTnFABCJdZZID8kmG2J6grVRx18G9xSKfl7nKVz3w,2797
221
221
  django_cfg/apps/dashboard/views/apizones_views.py,sha256=FtEEeNQD7aFBejmuTfdtjvRCLwCJyjD7AWDR1ouBo2k,2329
222
222
  django_cfg/apps/dashboard/views/charts_views.py,sha256=XDV3lTfoP65UuW_HIgNnp_80k35DVcicXXPLzIB6neU,5514
223
223
  django_cfg/apps/dashboard/views/commands_views.py,sha256=eJw3U4CtLUMZn2YdENr3HwhzHcqygo8HW92vjRg1sYQ,6099
224
- django_cfg/apps/dashboard/views/crontab_views.py,sha256=MWLD1ogx0XROnWoelbiWdXi9qkEHv0b9-teUfy97iXg,2439
224
+ django_cfg/apps/dashboard/views/django_q2_views.py,sha256=oQcMNDffZc0zB0Er-s2vUIRW_49yqKeEbxsyo9r32_U,2222
225
225
  django_cfg/apps/dashboard/views/overview_views.py,sha256=UZsGOUuZxYymziB0bPxBEfDaIHwFMGz6pCxNMLBRtsI,3680
226
226
  django_cfg/apps/dashboard/views/statistics_views.py,sha256=CISWM8A5lkIqTK2dWifTBJD4RdFI9Hu-_RCFl3kMoiA,3511
227
227
  django_cfg/apps/dashboard/views/system_views.py,sha256=PSEGZuHhexgBiKVOlrNlDV9_t2kEwS2arBT8h2KFxds,2459
@@ -509,6 +509,7 @@ django_cfg/apps/tasks/admin/task_log.py,sha256=H7gv8k7J_1rd31jmbMU6TKuDkzH_mx2be
509
509
  django_cfg/apps/tasks/filters/__init__.py,sha256=9H6dh9ryI_zJ0_tPENjsSS2V3Mx8MMcWze8hyHokfhc,151
510
510
  django_cfg/apps/tasks/filters/task_log.py,sha256=BY67R3jyzHR6XdhNty8gjGmLTC5VDTx2_tGeGODOJXE,4929
511
511
  django_cfg/apps/tasks/migrations/0001_initial.py,sha256=dVbEPP7umgjsJsubxaTYsrDq7dvwv2xf6_K8hfju-lE,7367
512
+ django_cfg/apps/tasks/migrations/0002_delete_tasklog.py,sha256=HW1ovU2mwvUXPhrVFaRorJW-rC-SlBNT0qUg6hG6vPY,283
512
513
  django_cfg/apps/tasks/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
513
514
  django_cfg/apps/tasks/models/__init__.py,sha256=4tvTev7IYkcjBrll3eLUFLJCDNlyG9c_863qoe_Fzu0,72
514
515
  django_cfg/apps/tasks/models/task_log.py,sha256=PxcQ7D3LNwQPy9IYLaBYL08buMHeakbmmXyr4Vgaqa0,7967
@@ -541,27 +542,27 @@ django_cfg/core/validation.py,sha256=QmwGlNDa0MFG2OUmgykIUAaEotT55YNh-wAWSVxOAos
541
542
  django_cfg/core/backends/__init__.py,sha256=5Qfza7oKQ8_UIHOs4ibhYvwtgAjngUqLrlwjKl_q124,38
542
543
  django_cfg/core/backends/smtp.py,sha256=kWkNMG7UwLsHcFYSKRgrk1HbP9mU1fxzWYnalHXqoL8,2308
543
544
  django_cfg/core/base/__init__.py,sha256=Z3bZvxejxk4vvWqmqTBLUi9XJpo6A_5Bq4R0J8q81Y4,116
544
- django_cfg/core/base/config_model.py,sha256=t5bChtbyMo1TXVuvh9gsi6wq2MY2khLmrGYqFlbwDr4,21348
545
+ django_cfg/core/base/config_model.py,sha256=fnmvjOs2fHTb8ifjFv0EsbVPFScG87ExikIqVAqpDZc,21810
545
546
  django_cfg/core/builders/__init__.py,sha256=jkInI7_jbxcjitapohw6QmbJPpacnnID6V1JovqtOFM,282
546
- django_cfg/core/builders/apps_builder.py,sha256=3mU7S0uko6JZWMFiQlH8_5hxUhQDajrR1iARqcOnge8,6680
547
+ django_cfg/core/builders/apps_builder.py,sha256=96o35vB7-eIzAv32bZ505H6lGmcxjqZmhUDsxbOQ4Ug,6675
547
548
  django_cfg/core/builders/middleware_builder.py,sha256=OwqQRoJKYWlXsQNPFBfUvVMYdppUHCPw-UDczV_esYg,3101
548
549
  django_cfg/core/builders/security_builder.py,sha256=W8Lk9eTMi3PuNK5qH-BIHegeE0cbvmuHKTumLcwOAh8,23961
549
550
  django_cfg/core/environment/__init__.py,sha256=sMOIe9z1i51j8B1VGjpLHJMaeDsBfsgn1TmL03FIeNo,141
550
551
  django_cfg/core/environment/detector.py,sha256=bI9k4fdK8Nbfl61ZcQ3yNbm3WlmK-L0xB-g-aXKUdhA,8923
551
552
  django_cfg/core/generation/__init__.py,sha256=0cYgeQ5EDN6sscQuFnXsFCy6m1BKgv_izNz0a1TlYSc,1355
552
553
  django_cfg/core/generation/generation.py,sha256=uLLJnJ_9kq8zV_auySK05dXwZB-BJx920mID0Pm4RCo,2524
553
- django_cfg/core/generation/orchestrator.py,sha256=l_fS7QpSO66ZhJZeQZj0FwI_l1AUI-3Zir-3aIxDaUw,11996
554
+ django_cfg/core/generation/orchestrator.py,sha256=GdR5HBjuDE4Rxzj8q6_mm24XbIJd7cORncHGYgCCwkI,12046
554
555
  django_cfg/core/generation/protocols.py,sha256=9pqGsZD_Y5v3jdYp4YdkL-i--8feuvX_iKXxV-Cc4Bg,676
555
556
  django_cfg/core/generation/core_generators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
556
557
  django_cfg/core/generation/core_generators/settings.py,sha256=Rto9qjqQC-MeQJMNyoflS91RrNDS_lBNH4d4ZtgER-8,2632
557
558
  django_cfg/core/generation/core_generators/static.py,sha256=7xo7F9DSbz5Gk2Di-SbBo0petNMX4ZKfS8wuQCe9lz8,2747
558
559
  django_cfg/core/generation/core_generators/templates.py,sha256=XeGKzF790_zKwFdRw3FN-VHCEgw6Q1dWPX7C1tNas1s,4885
559
560
  django_cfg/core/generation/data_generators/__init__.py,sha256=O7cmt_k34hWRgrdaAzCRPudcaowaOwMgaoXmZY8HG54,298
560
- django_cfg/core/generation/data_generators/cache.py,sha256=bdcbnaDarl_8UQ18gk7bIKrQ9PDZOhpDAVjCEgYVeUU,3840
561
+ django_cfg/core/generation/data_generators/cache.py,sha256=UvBmkmiUMPTaA5PDuOdMH1RgpvUz7xvX7jlWe4GUCsg,4920
561
562
  django_cfg/core/generation/data_generators/database.py,sha256=mYR2mBvqWU93YP9XUUVlcZaQJtSNeAQ7Dk4Vj6Tu95k,3481
562
- django_cfg/core/generation/integration_generators/__init__.py,sha256=1HQ98jj5MNGXy7Vq9uJ0wZI1k50nVzTnnyrrmB1-XCw,712
563
+ django_cfg/core/generation/integration_generators/__init__.py,sha256=wPPiVQnmCEXKigp-d_jKznU2i1M6aP4P2YOVYipuMDk,737
563
564
  django_cfg/core/generation/integration_generators/api.py,sha256=Xsyu3mYyq9mje8QGNSU0Yp4tLbtF0ckq4lEf_Rj5pLc,11062
564
- django_cfg/core/generation/integration_generators/crontab.py,sha256=b-oVQ48LoN550I0pGla77FK_v__6gwTihsXtnMQLO8k,1703
565
+ django_cfg/core/generation/integration_generators/django_q2.py,sha256=ZRIApW0lQWHOizd9jvFBSckk_O-bhrgr7rCnKg7M8U0,4155
565
566
  django_cfg/core/generation/integration_generators/sessions.py,sha256=GbRC72Gny4dzj7oTIrbuhYyvhCQBoWI-0GxB8ZHTrEU,1644
566
567
  django_cfg/core/generation/integration_generators/tailwind.py,sha256=YgiV5c-l0DDJnMKx6mWcUtH5zyMdewAJXjLDwmHrSuc,1208
567
568
  django_cfg/core/generation/integration_generators/tasks.py,sha256=fMbuIdjRenuZQ6rfco7imLzDbCdX4WEO1aLslBpxjTQ,2253
@@ -624,7 +625,7 @@ django_cfg/middleware/user_activity.py,sha256=bgftHXXeGBS-jCa8mLzTx4Gcz2fHTaQz_n
624
625
  django_cfg/mixins/__init__.py,sha256=1IErIlF4QWqt9VLFD8yoTiGWHobsDjLL6rqcEqMLbw4,211
625
626
  django_cfg/mixins/admin_api.py,sha256=3GRfAty6YXGbZp4ZFsNFt1Gs_e5T4xBOLnRPoc5vaq0,1116
626
627
  django_cfg/mixins/client_api.py,sha256=KeGK_f2xR08l0ckGpMmXHHpVLDQ7SnSbZn4WP5bSsvI,1200
627
- django_cfg/models/__init__.py,sha256=DsX8Xkgu8Qji7-lcWetnwZkI6r9wSUcEXr1ZVs2Zk88,2867
628
+ django_cfg/models/__init__.py,sha256=H11Jdcv5CaKMq6ylk8o3s7Orc6Yr8wQJ6lL1n7EMiZI,2883
628
629
  django_cfg/models/api/__init__.py,sha256=VWkiYs38A7Tx5ZWePeBxL1lMiXKsonb5TQfoVRRCBac,605
629
630
  django_cfg/models/api/config.py,sha256=KzaDn2Ubc7SpZ_8xt6-Q-XxnZbf9Glu1xJhJWbAI--o,4455
630
631
  django_cfg/models/api/cors.py,sha256=kRDGD-HcCK39QhoyvKnn2yGcwzGFp2QIw50G7TNx78I,3467
@@ -639,11 +640,11 @@ django_cfg/models/api/drf/swagger.py,sha256=ku_eE7bWgHxjXD6Z2sEKSYE-bIzmZfAR0vQW
639
640
  django_cfg/models/base/__init__.py,sha256=f6sMVyd-YEFdLebmIKOOPviu1Ovn4BHGp7j7ZVNqFDo,271
640
641
  django_cfg/models/base/config.py,sha256=hfpf35yMR8oOE1J0SBPNNSBwXckK3F2-Iv0Vw6cNX4E,10114
641
642
  django_cfg/models/base/module.py,sha256=nxN1Y9J4l94kOfSXLQJ2eGgIGWTq8kyh7hUGvCQNyIs,2674
642
- django_cfg/models/django/__init__.py,sha256=9jhiJgF7R4fqjy_p13FuKVn4CjhU-MAZgiXk_OQwAf0,495
643
+ django_cfg/models/django/__init__.py,sha256=J4VRl77vgXzfKcdUcX-sPxpBSOJ4qA-8RstPgJ5ChmA,511
643
644
  django_cfg/models/django/axes.py,sha256=-4nk2gSfpj7lNY5vnm_2jHVLz8VAKoEd9yF2TuCR8O8,5624
644
645
  django_cfg/models/django/constance.py,sha256=6x57bi40mDX0fKcKeQKgV2BO3WIVYPQllAchWsj4KvM,8847
645
- django_cfg/models/django/crontab.py,sha256=HoD3CRhE3Lfo_pnKdm32pgeEz7J4MiJqI6WuOpR03G0,8816
646
646
  django_cfg/models/django/crypto_fields.py,sha256=OguITidM4Mp564p_gbsokeNCZxjL9hrK1Vw0McuA3yo,4700
647
+ django_cfg/models/django/django_q2.py,sha256=9i-ogZJ24YZJ9Xf0CoLs_tvg9FkYhrZoOd4KurDwYnY,14378
647
648
  django_cfg/models/django/environment.py,sha256=lBCHBs1lphv9tlu1BCTfLZeH_kUame0p66A_BIjBY7M,9440
648
649
  django_cfg/models/django/openapi.py,sha256=avE3iapaCj8eyOqVUum_v2EExR3V-hwHrexqtXMHtTQ,3739
649
650
  django_cfg/models/django/revolution_legacy.py,sha256=Z4SPUS7QSv62EuPAeFFoXGEgqLmdXnVEr7Ofk1IDtVc,8918
@@ -1001,7 +1002,7 @@ django_cfg/modules/nextjs_admin/models/config.py,sha256=75iM81aaTlDQdhfvdlCzj6o9
1001
1002
  django_cfg/modules/nextjs_admin/templatetags/__init__.py,sha256=ChVBnJggCIY8rMhfyJFoA8k0qKo-8FtJknrk54Vx4wM,51
1002
1003
  django_cfg/modules/nextjs_admin/templatetags/nextjs_admin.py,sha256=aAekrlu3pvvx3I4uJGT3S2ie8QfF94umDBjgAF71EII,4483
1003
1004
  django_cfg/registry/__init__.py,sha256=CaiL9KwqPzXlIe5-4Qr7PQu5ZxAW1HtuDIXZ7-ktRQg,538
1004
- django_cfg/registry/core.py,sha256=Lli6B4wi775mo2piMYmnVi2SV21SeB1jCcMXpEaGzdw,3533
1005
+ django_cfg/registry/core.py,sha256=LqqmWwaOo-0KivPD61yolBwxxigvKARZflOv6rLAcHM,3546
1005
1006
  django_cfg/registry/exceptions.py,sha256=b4pIakeRxhT1-ST3lbAnmAQaASRBARCoah_w6vb3VF0,399
1006
1007
  django_cfg/registry/modules.py,sha256=DC9veh6DdnqOa_KPNwDhnxvvNKRNF0Um2isHn1XGoxU,1915
1007
1008
  django_cfg/registry/services.py,sha256=l0V2twGpF9BwVlo-TTfFu8dV7GVBS7XKCsScIZXWWbc,2457
@@ -1024,7 +1025,7 @@ django_cfg/static/admin/js/alpine/commands-section.js,sha256=8z2MQNwZF9Tx_2EK1AY
1024
1025
  django_cfg/static/admin/js/alpine/dashboard-tabs.js,sha256=ob8Q_I9lFLDv_hFERXgTyvqMDBspAGfzCxI_7slRur4,1354
1025
1026
  django_cfg/static/admin/js/alpine/system-metrics.js,sha256=m-Fg55K_vpHXToD46PXL9twl4OBF_V9MONvbSWbQqDw,440
1026
1027
  django_cfg/static/admin/js/alpine/toggle-section.js,sha256=T141NFmy0fRJyGGuuaCJRjJXwPam-xxtQNW1hi8BJbc,672
1027
- django_cfg/static/frontend/admin.zip,sha256=s-9EflEZEJ3Sf5ceavbhr8f_zY9rpvfRxUN05pHaiWQ,7648668
1028
+ django_cfg/static/frontend/admin.zip,sha256=3ezv0j07V1jtVJA3wjxwr1T6Z4XoA3xRhRIFOAZCOm8,7647333
1028
1029
  django_cfg/static/js/api-loader.mjs,sha256=boGqqRGnFR-Mzo_RQOjhAzNvsb7QxZddSwMKROzkk9Q,5163
1029
1030
  django_cfg/static/js/api/base.mjs,sha256=KUxZHHdELAV8mNnACpwJRvaQhdJxp-n5LFEQ4oUZxBo,4707
1030
1031
  django_cfg/static/js/api/index.mjs,sha256=_-Q04jjHcgwi4CGfiaLyiOR6NW7Yu1HBhJWp2J1cjpc,2538
@@ -1059,9 +1060,9 @@ django_cfg/utils/version_check.py,sha256=WO51J2m2e-wVqWCRwbultEwu3q1lQasV67Mw2aa
1059
1060
  django_cfg/CHANGELOG.md,sha256=jtT3EprqEJkqSUh7IraP73vQ8PmKUMdRtznQsEnqDZk,2052
1060
1061
  django_cfg/CONTRIBUTING.md,sha256=DU2kyQ6PU0Z24ob7O_OqKWEYHcZmJDgzw-lQCmu6uBg,3041
1061
1062
  django_cfg/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
1062
- django_cfg/pyproject.toml,sha256=TLXG65JQdG5kAmO1VamAJ4C4UJsPLetDT_EyHXBTV08,8667
1063
- django_cfg-1.4.113.dist-info/METADATA,sha256=DDSCrssFZlKGf2PkB1pkJ1gejD6s0FgA3wZVzKljJx4,23878
1064
- django_cfg-1.4.113.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
1065
- django_cfg-1.4.113.dist-info/entry_points.txt,sha256=Ucmde4Z2wEzgb4AggxxZ0zaYDb9HpyE5blM3uJ0_VNg,56
1066
- django_cfg-1.4.113.dist-info/licenses/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
1067
- django_cfg-1.4.113.dist-info/RECORD,,
1063
+ django_cfg/pyproject.toml,sha256=kAwzl-dSNGJtDEsF7j8PufTqwQrVq1eMy4zCLm9zf_M,8681
1064
+ django_cfg-1.4.114.dist-info/METADATA,sha256=a8yk0DiKdgIIOHcPGyVpXxyPVvv-El4ju0Hp1t_55Qw,23904
1065
+ django_cfg-1.4.114.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
1066
+ django_cfg-1.4.114.dist-info/entry_points.txt,sha256=Ucmde4Z2wEzgb4AggxxZ0zaYDb9HpyE5blM3uJ0_VNg,56
1067
+ django_cfg-1.4.114.dist-info/licenses/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
1068
+ django_cfg-1.4.114.dist-info/RECORD,,
@@ -1,84 +0,0 @@
1
- """
2
- Crontab Serializers
3
-
4
- Serializers for crontab monitoring endpoints.
5
- """
6
-
7
- from rest_framework import serializers
8
-
9
-
10
- class CrontabJobSerializer(serializers.Serializer):
11
- """
12
- Serializer for individual cron job configuration.
13
-
14
- Maps to CrontabJobConfig Pydantic model.
15
- """
16
-
17
- name = serializers.CharField(help_text="Job identifier name")
18
- job_type = serializers.ChoiceField(
19
- choices=['command', 'callable'],
20
- help_text="Job type: Django command or Python callable"
21
- )
22
- command = serializers.CharField(
23
- required=False,
24
- allow_null=True,
25
- help_text="Management command name (for command type jobs)"
26
- )
27
- callable_path = serializers.CharField(
28
- required=False,
29
- allow_null=True,
30
- help_text="Python callable path (for callable type jobs)"
31
- )
32
- command_args = serializers.ListField(
33
- child=serializers.CharField(),
34
- required=False,
35
- help_text="Command positional arguments"
36
- )
37
- command_kwargs = serializers.DictField(
38
- required=False,
39
- help_text="Command keyword arguments"
40
- )
41
- minute = serializers.CharField(help_text="Cron minute field")
42
- hour = serializers.CharField(help_text="Cron hour field")
43
- day_of_month = serializers.CharField(help_text="Cron day of month field")
44
- month_of_year = serializers.CharField(help_text="Cron month field")
45
- day_of_week = serializers.CharField(help_text="Cron day of week field")
46
- enabled = serializers.BooleanField(help_text="Whether job is enabled")
47
- comment = serializers.CharField(
48
- required=False,
49
- allow_null=True,
50
- help_text="Optional job description"
51
- )
52
- schedule_display = serializers.CharField(
53
- required=False,
54
- help_text="Human-readable schedule description"
55
- )
56
-
57
-
58
- class CrontabJobsSerializer(serializers.Serializer):
59
- """Serializer for list of all cron jobs."""
60
-
61
- enabled = serializers.BooleanField(help_text="Whether crontab is enabled")
62
- jobs_count = serializers.IntegerField(help_text="Total number of jobs")
63
- enabled_jobs_count = serializers.IntegerField(help_text="Number of enabled jobs")
64
- jobs = CrontabJobSerializer(many=True, help_text="List of all cron jobs")
65
-
66
-
67
- class CrontabStatusSerializer(serializers.Serializer):
68
- """Serializer for crontab configuration status."""
69
-
70
- enabled = serializers.BooleanField(help_text="Whether crontab is enabled")
71
- jobs_count = serializers.IntegerField(help_text="Total number of jobs")
72
- enabled_jobs_count = serializers.IntegerField(help_text="Number of enabled jobs")
73
- lock_jobs = serializers.BooleanField(help_text="Whether job locking is enabled")
74
- command_prefix = serializers.CharField(
75
- required=False,
76
- allow_null=True,
77
- help_text="Command prefix for all jobs"
78
- )
79
- comment = serializers.CharField(
80
- required=False,
81
- allow_null=True,
82
- help_text="Crontab configuration comment"
83
- )
84
- timestamp = serializers.CharField(help_text="Status check timestamp (ISO format)")
@@ -1,210 +0,0 @@
1
- """
2
- Crontab Service
3
-
4
- Business logic for crontab/scheduled jobs monitoring and information.
5
- """
6
-
7
- import logging
8
- from datetime import datetime
9
- from typing import Any, Dict, List
10
-
11
- logger = logging.getLogger(__name__)
12
-
13
-
14
- class CrontabService:
15
- """
16
- Service for crontab monitoring and information.
17
-
18
- %%PRIORITY:HIGH%%
19
- %%AI_HINT: Provides information about scheduled cron jobs%%
20
-
21
- TAGS: crontab, scheduling, monitoring, service
22
- DEPENDS_ON: [django_cfg.core.config]
23
- """
24
-
25
- def __init__(self):
26
- """Initialize crontab service."""
27
- self.logger = logger
28
-
29
- def _get_schedule_display(self, job) -> str:
30
- """
31
- Generate human-readable schedule description.
32
-
33
- Args:
34
- job: CrontabJobConfig instance
35
-
36
- Returns:
37
- Human-readable schedule string
38
- """
39
- parts = []
40
-
41
- # Minute
42
- if job.minute == "*":
43
- parts.append("every minute")
44
- elif job.minute.startswith("*/"):
45
- interval = job.minute[2:]
46
- parts.append(f"every {interval} minutes")
47
- else:
48
- parts.append(f"at minute {job.minute}")
49
-
50
- # Hour
51
- if job.hour == "*":
52
- parts.append("of every hour")
53
- elif job.hour.startswith("*/"):
54
- interval = job.hour[2:]
55
- parts.append(f"every {interval} hours")
56
- else:
57
- parts.append(f"at {job.hour}:00")
58
-
59
- # Day of month
60
- if job.day_of_month != "*":
61
- parts.append(f"on day {job.day_of_month}")
62
-
63
- # Month
64
- if job.month_of_year != "*":
65
- months = {
66
- "1": "January", "2": "February", "3": "March", "4": "April",
67
- "5": "May", "6": "June", "7": "July", "8": "August",
68
- "9": "September", "10": "October", "11": "November", "12": "December"
69
- }
70
- month_name = months.get(job.month_of_year, job.month_of_year)
71
- parts.append(f"in {month_name}")
72
-
73
- # Day of week
74
- if job.day_of_week != "*":
75
- days = {
76
- "0": "Sunday", "1": "Monday", "2": "Tuesday", "3": "Wednesday",
77
- "4": "Thursday", "5": "Friday", "6": "Saturday"
78
- }
79
- if "-" in job.day_of_week:
80
- parts.append(f"on weekdays ({job.day_of_week})")
81
- else:
82
- day_name = days.get(job.day_of_week, job.day_of_week)
83
- parts.append(f"on {day_name}")
84
-
85
- return " ".join(parts)
86
-
87
- def _format_job(self, job) -> Dict[str, Any]:
88
- """
89
- Format a single job for API response.
90
-
91
- Args:
92
- job: CrontabJobConfig instance
93
-
94
- Returns:
95
- Formatted job dictionary
96
- """
97
- job_data = {
98
- 'name': job.name,
99
- 'job_type': job.job_type,
100
- 'minute': job.minute,
101
- 'hour': job.hour,
102
- 'day_of_month': job.day_of_month,
103
- 'month_of_year': job.month_of_year,
104
- 'day_of_week': job.day_of_week,
105
- 'enabled': job.enabled,
106
- 'schedule_display': self._get_schedule_display(job),
107
- }
108
-
109
- # Add command or callable info
110
- if job.job_type == 'command':
111
- job_data['command'] = job.command
112
- if job.command_args:
113
- job_data['command_args'] = job.command_args
114
- if job.command_kwargs:
115
- job_data['command_kwargs'] = job.command_kwargs
116
- else:
117
- job_data['callable_path'] = job.callable_path
118
-
119
- # Add comment if present
120
- if job.comment:
121
- job_data['comment'] = job.comment
122
-
123
- return job_data
124
-
125
- def get_all_jobs(self) -> Dict[str, Any]:
126
- """
127
- Get all configured cron jobs.
128
-
129
- Returns:
130
- Dictionary with jobs list and summary
131
-
132
- USED_BY: CrontabViewSet.jobs endpoint
133
- """
134
- try:
135
- from django_cfg.core.config import get_current_config
136
-
137
- config = get_current_config()
138
-
139
- # Check if crontab is configured
140
- if not hasattr(config, 'crontab') or not config.crontab:
141
- return {
142
- 'enabled': False,
143
- 'jobs_count': 0,
144
- 'enabled_jobs_count': 0,
145
- 'jobs': []
146
- }
147
-
148
- crontab_config = config.crontab
149
-
150
- # Format all jobs
151
- jobs = [self._format_job(job) for job in crontab_config.jobs]
152
-
153
- # Count enabled jobs
154
- enabled_jobs_count = sum(1 for job in crontab_config.jobs if job.enabled)
155
-
156
- return {
157
- 'enabled': crontab_config.enabled,
158
- 'jobs_count': len(jobs),
159
- 'enabled_jobs_count': enabled_jobs_count,
160
- 'jobs': jobs
161
- }
162
-
163
- except Exception as e:
164
- self.logger.error(f"Failed to get cron jobs: {e}", exc_info=True)
165
- raise
166
-
167
- def get_status(self) -> Dict[str, Any]:
168
- """
169
- Get crontab configuration status and summary.
170
-
171
- Returns:
172
- Dictionary with crontab configuration status
173
-
174
- USED_BY: CrontabViewSet.crontab_status endpoint
175
- """
176
- try:
177
- from django_cfg.core.config import get_current_config
178
-
179
- config = get_current_config()
180
-
181
- # Check if crontab is configured
182
- if not hasattr(config, 'crontab') or not config.crontab:
183
- return {
184
- 'enabled': False,
185
- 'jobs_count': 0,
186
- 'enabled_jobs_count': 0,
187
- 'lock_jobs': False,
188
- 'command_prefix': None,
189
- 'comment': None,
190
- 'timestamp': datetime.now().isoformat(),
191
- }
192
-
193
- crontab_config = config.crontab
194
-
195
- # Count enabled jobs
196
- enabled_jobs_count = sum(1 for job in crontab_config.jobs if job.enabled)
197
-
198
- return {
199
- 'enabled': crontab_config.enabled,
200
- 'jobs_count': len(crontab_config.jobs),
201
- 'enabled_jobs_count': enabled_jobs_count,
202
- 'lock_jobs': crontab_config.lock_jobs,
203
- 'command_prefix': crontab_config.command_prefix,
204
- 'comment': crontab_config.comment,
205
- 'timestamp': datetime.now().isoformat(),
206
- }
207
-
208
- except Exception as e:
209
- self.logger.error(f"Failed to get crontab status: {e}", exc_info=True)
210
- raise
@@ -1,72 +0,0 @@
1
- """
2
- Crontab ViewSet
3
-
4
- Endpoints for cron job monitoring:
5
- - GET /crontab/jobs/ - List all configured cron jobs
6
- - GET /crontab/status/ - Crontab configuration status
7
- """
8
-
9
- import logging
10
-
11
- from drf_spectacular.utils import extend_schema
12
- from rest_framework import status, viewsets
13
-
14
- from django_cfg.mixins import AdminAPIMixin
15
- from rest_framework.decorators import action
16
- from rest_framework.response import Response
17
-
18
- from ..services import CrontabService
19
- from ..serializers import CrontabJobsSerializer, CrontabStatusSerializer
20
-
21
- logger = logging.getLogger(__name__)
22
-
23
-
24
- class CrontabViewSet(AdminAPIMixin, viewsets.GenericViewSet):
25
- """
26
- Crontab Monitoring ViewSet
27
-
28
- Provides endpoints for monitoring scheduled cron jobs.
29
- Requires admin authentication (JWT, Session, or Basic Auth).
30
- """
31
-
32
- serializer_class = CrontabJobsSerializer
33
-
34
- @extend_schema(
35
- summary="Get all cron jobs",
36
- description="Retrieve list of all configured cron jobs with schedules and details",
37
- responses={200: CrontabJobsSerializer},
38
- tags=["Dashboard - Crontab"]
39
- )
40
- @action(detail=False, methods=['get'], url_path='jobs', serializer_class=CrontabJobsSerializer)
41
- def jobs(self, request):
42
- """Get all configured cron jobs."""
43
- try:
44
- crontab_service = CrontabService()
45
- jobs_data = crontab_service.get_all_jobs()
46
- return Response(jobs_data)
47
-
48
- except Exception as e:
49
- logger.error(f"Crontab jobs API error: {e}", exc_info=True)
50
- return Response({
51
- 'error': str(e)
52
- }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
53
-
54
- @extend_schema(
55
- summary="Get crontab status",
56
- description="Retrieve crontab configuration status and summary",
57
- responses={200: CrontabStatusSerializer},
58
- tags=["Dashboard - Crontab"]
59
- )
60
- @action(detail=False, methods=['get'], url_path='status', serializer_class=CrontabStatusSerializer)
61
- def crontab_status(self, request):
62
- """Get crontab configuration status."""
63
- try:
64
- crontab_service = CrontabService()
65
- status_data = crontab_service.get_status()
66
- return Response(status_data)
67
-
68
- except Exception as e:
69
- logger.error(f"Crontab status API error: {e}", exc_info=True)
70
- return Response({
71
- 'error': str(e)
72
- }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
@@ -1,64 +0,0 @@
1
- """
2
- Crontab settings generator for django-cfg.
3
-
4
- Generates django-crontab settings and handles INSTALLED_APPS integration.
5
- """
6
-
7
- from typing import TYPE_CHECKING, Any, Dict
8
-
9
- from django_cfg.modules.django_logging import logger
10
-
11
- if TYPE_CHECKING:
12
- from django_cfg.models.django.crontab import CrontabConfig
13
-
14
-
15
- class CrontabSettingsGenerator:
16
- """
17
- Generates crontab scheduling settings for django-crontab.
18
-
19
- Automatically:
20
- - Generates CRONJOBS configuration
21
- - Adds django_crontab to INSTALLED_APPS if enabled
22
- - Configures lock files and command prefixes
23
- """
24
-
25
- def __init__(self, config: "CrontabConfig"):
26
- """
27
- Initialize with crontab configuration.
28
-
29
- Args:
30
- config: CrontabConfig instance
31
- """
32
- self.config = config
33
-
34
- def generate(self) -> Dict[str, Any]:
35
- """
36
- Generate crontab settings.
37
-
38
- Returns:
39
- Dictionary with crontab configuration
40
- """
41
- if not self.config or not self.config.enabled:
42
- return {}
43
-
44
- settings = self.config.to_django_settings()
45
-
46
- # Log configuration
47
- enabled_jobs = self.config.get_enabled_jobs()
48
- if enabled_jobs:
49
- logger.info(
50
- f"✓ Configured {len(enabled_jobs)} crontab job(s) "
51
- f"[django-crontab integration]"
52
- )
53
-
54
- # Log individual jobs in debug mode
55
- for job in enabled_jobs:
56
- logger.debug(
57
- f" - {job.name}: {job.schedule} → "
58
- f"{job.command if job.job_type == 'command' else job.callable_path}"
59
- )
60
-
61
- return settings
62
-
63
-
64
- __all__ = ["CrontabSettingsGenerator"]