django-cfg 1.4.116__py3-none-any.whl → 1.4.118__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.
- django_cfg/__init__.py +1 -1
- django_cfg/core/builders/apps_builder.py +2 -0
- django_cfg/models/django/django_q2.py +22 -4
- django_cfg/modules/django_q2/README.md +140 -0
- django_cfg/modules/django_q2/__init__.py +8 -0
- django_cfg/modules/django_q2/apps.py +107 -0
- django_cfg/modules/django_q2/management/__init__.py +0 -0
- django_cfg/modules/django_q2/management/commands/__init__.py +0 -0
- django_cfg/modules/django_q2/management/commands/sync_django_q_schedules.py +74 -0
- django_cfg/pyproject.toml +2 -2
- {django_cfg-1.4.116.dist-info → django_cfg-1.4.118.dist-info}/METADATA +1 -2
- {django_cfg-1.4.116.dist-info → django_cfg-1.4.118.dist-info}/RECORD +15 -9
- {django_cfg-1.4.116.dist-info → django_cfg-1.4.118.dist-info}/WHEEL +0 -0
- {django_cfg-1.4.116.dist-info → django_cfg-1.4.118.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.4.116.dist-info → django_cfg-1.4.118.dist-info}/licenses/LICENSE +0 -0
django_cfg/__init__.py
CHANGED
|
@@ -166,6 +166,8 @@ class InstalledAppsBuilder:
|
|
|
166
166
|
# Add django-q2 if enabled
|
|
167
167
|
if hasattr(self.config, "django_q2") and self.config.django_q2 and self.config.django_q2.enabled:
|
|
168
168
|
apps.append("django_q")
|
|
169
|
+
# Auto-add django_q2 module for automatic schedule synchronization
|
|
170
|
+
apps.append("django_cfg.modules.django_q2")
|
|
169
171
|
|
|
170
172
|
# Add DRF Tailwind theme module (uses Tailwind via CDN)
|
|
171
173
|
if self.config.enable_drf_tailwind:
|
|
@@ -227,8 +227,11 @@ class DjangoQ2ScheduleConfig(BaseModel):
|
|
|
227
227
|
"next_run": timezone.now() + timedelta(seconds=10),
|
|
228
228
|
}
|
|
229
229
|
|
|
230
|
+
# Convert args list to tuple for Django-Q2 scheduler compatibility
|
|
231
|
+
# Django-Q2 scheduler.py:66-69 expects tuple format, not list
|
|
232
|
+
# If list is provided, scheduler wraps it: (list,) instead of converting list -> tuple
|
|
230
233
|
if self.args:
|
|
231
|
-
config["args"] = self.args
|
|
234
|
+
config["args"] = tuple(self.args) if isinstance(self.args, list) else self.args
|
|
232
235
|
|
|
233
236
|
if self.kwargs:
|
|
234
237
|
config["kwargs"] = self.kwargs
|
|
@@ -299,6 +302,19 @@ class DjangoQ2Config(BaseModel):
|
|
|
299
302
|
)
|
|
300
303
|
```
|
|
301
304
|
|
|
305
|
+
Schedule Synchronization (AUTOMATIC):
|
|
306
|
+
When Django-Q2 is enabled, schedules are automatically synced after migrations.
|
|
307
|
+
|
|
308
|
+
The module 'django_cfg.modules.django_q2' is automatically added to INSTALLED_APPS
|
|
309
|
+
when django_q2.enabled=True, so you don't need to add it manually.
|
|
310
|
+
|
|
311
|
+
It uses Django's post_migrate signal to sync schedules from config to database.
|
|
312
|
+
|
|
313
|
+
Manual sync (optional):
|
|
314
|
+
```bash
|
|
315
|
+
python manage.py sync_django_q_schedules
|
|
316
|
+
```
|
|
317
|
+
|
|
302
318
|
Admin interface:
|
|
303
319
|
- Visit /admin/django_q/ to view tasks and schedules
|
|
304
320
|
- Monitor task execution, failures, and performance
|
|
@@ -464,10 +480,12 @@ class DjangoQ2Config(BaseModel):
|
|
|
464
480
|
"orm": "default",
|
|
465
481
|
}
|
|
466
482
|
|
|
467
|
-
#
|
|
483
|
+
# CRITICAL FIX: Django-Q2 uses 'redis' parameter, NOT 'broker'!
|
|
484
|
+
# The 'broker' parameter is ignored by django-q2.
|
|
485
|
+
# We must set 'redis' parameter to the broker_url string.
|
|
468
486
|
if self.broker_class == "redis":
|
|
469
|
-
#
|
|
470
|
-
|
|
487
|
+
# Set redis parameter to broker_url (Django-Q2 accepts redis:// URL string)
|
|
488
|
+
cluster_config["redis"] = broker_url
|
|
471
489
|
|
|
472
490
|
settings = {
|
|
473
491
|
"Q_CLUSTER": cluster_config
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# Django-Q2 Module
|
|
2
|
+
|
|
3
|
+
Автоматическая синхронизация расписаний Django-Q2 из конфига в базу данных.
|
|
4
|
+
|
|
5
|
+
## Зачем это нужно?
|
|
6
|
+
|
|
7
|
+
Django-Q2 хранит расписания в базе данных, но **не создаёт их автоматически** из конфига.
|
|
8
|
+
Этот модуль решает эту проблему - синхронизирует расписания после каждой миграции.
|
|
9
|
+
|
|
10
|
+
## Использование
|
|
11
|
+
|
|
12
|
+
### 1. Включи Django-Q2 в конфиге
|
|
13
|
+
|
|
14
|
+
```python
|
|
15
|
+
# config.py
|
|
16
|
+
from django_cfg.models.django import DjangoQ2Config
|
|
17
|
+
|
|
18
|
+
django_q2 = DjangoQ2Config(
|
|
19
|
+
enabled=True, # ← Автоматически добавит django_q и django_cfg.modules.django_q2 в INSTALLED_APPS
|
|
20
|
+
schedules=[...]
|
|
21
|
+
)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Модуль подключается автоматически!** Не нужно вручную добавлять в INSTALLED_APPS.
|
|
25
|
+
|
|
26
|
+
### 2. Определи расписания в конфиге
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
from django_cfg.models.django import DjangoQ2Config, DjangoQ2ScheduleConfig
|
|
30
|
+
|
|
31
|
+
django_q2 = DjangoQ2Config(
|
|
32
|
+
enabled=True,
|
|
33
|
+
schedules=[
|
|
34
|
+
DjangoQ2ScheduleConfig(
|
|
35
|
+
name="Sync balances hourly",
|
|
36
|
+
schedule_type="hourly",
|
|
37
|
+
command="sync_account_balances",
|
|
38
|
+
command_args=["--verbose"],
|
|
39
|
+
),
|
|
40
|
+
DjangoQ2ScheduleConfig(
|
|
41
|
+
name="Cleanup daily",
|
|
42
|
+
schedule_type="cron",
|
|
43
|
+
cron="0 2 * * *", # 2 AM каждый день
|
|
44
|
+
command="cleanup_old_data",
|
|
45
|
+
command_kwargs={"days": 30},
|
|
46
|
+
),
|
|
47
|
+
],
|
|
48
|
+
)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 3. Запусти миграции
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
python manage.py migrate
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Вывод:**
|
|
58
|
+
```
|
|
59
|
+
Running migrations:
|
|
60
|
+
...
|
|
61
|
+
Syncing 2 Django-Q2 schedule(s)...
|
|
62
|
+
✓ Created schedule: Sync balances hourly
|
|
63
|
+
✓ Created schedule: Cleanup daily
|
|
64
|
+
✅ Django-Q2 schedules synced: 2 created, 0 updated
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### 4. Запусти qcluster
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
python manage.py qcluster
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Готово! Расписания автоматически синхронизированы и работают.
|
|
74
|
+
|
|
75
|
+
## Как это работает?
|
|
76
|
+
|
|
77
|
+
1. **Модуль подключается** к сигналу `post_migrate`
|
|
78
|
+
2. **После миграций** автоматически:
|
|
79
|
+
- Читает расписания из конфига
|
|
80
|
+
- Создаёт/обновляет их в базе данных (Schedule model)
|
|
81
|
+
3. **Django-Q2 читает** расписания из базы и выполняет задачи
|
|
82
|
+
|
|
83
|
+
## Ручная синхронизация (опционально)
|
|
84
|
+
|
|
85
|
+
Если нужно синхронизировать без миграций:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
python manage.py sync_django_q_schedules
|
|
89
|
+
|
|
90
|
+
# Или с --dry-run для проверки:
|
|
91
|
+
python manage.py sync_django_q_schedules --dry-run
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Безопасность
|
|
95
|
+
|
|
96
|
+
- ✅ **Идемпотентность**: можно запускать много раз, не создаст дубликаты
|
|
97
|
+
- ✅ **Без race conditions**: синхронизация происходит один раз за цикл миграций
|
|
98
|
+
- ✅ **Graceful degradation**: если Django-Q2 не установлен, модуль просто молча пропустит синхронизацию
|
|
99
|
+
- ✅ **Logging**: все операции логируются для отладки
|
|
100
|
+
|
|
101
|
+
## Преимущества перед ручной синхронизацией
|
|
102
|
+
|
|
103
|
+
| Аспект | Ручная синхронизация | Модуль |
|
|
104
|
+
|--------|---------------------|--------|
|
|
105
|
+
| Автоматизация | Нужно помнить запускать | Автоматически |
|
|
106
|
+
| Деплой | Легко забыть | Всегда синхронизировано |
|
|
107
|
+
| CI/CD | Нужно добавлять в скрипты | Работает из коробки |
|
|
108
|
+
| Ошибки | Легко пропустить | Логи миграций |
|
|
109
|
+
|
|
110
|
+
## Troubleshooting
|
|
111
|
+
|
|
112
|
+
### Расписания не создаются
|
|
113
|
+
|
|
114
|
+
Проверь:
|
|
115
|
+
1. Модуль добавлен в INSTALLED_APPS
|
|
116
|
+
2. `django_q2.enabled = True` в конфиге
|
|
117
|
+
3. В конфиге есть расписания
|
|
118
|
+
4. Миграции запущены: `python manage.py migrate`
|
|
119
|
+
|
|
120
|
+
### Расписания не обновляются
|
|
121
|
+
|
|
122
|
+
Запусти миграции повторно или используй ручную синхронизацию:
|
|
123
|
+
```bash
|
|
124
|
+
python manage.py migrate --run-syncdb
|
|
125
|
+
# или
|
|
126
|
+
python manage.py sync_django_q_schedules
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Логи синхронизации
|
|
130
|
+
|
|
131
|
+
Включи DEBUG логи:
|
|
132
|
+
```python
|
|
133
|
+
LOGGING = {
|
|
134
|
+
'loggers': {
|
|
135
|
+
'django_cfg.modules.django_q2': {
|
|
136
|
+
'level': 'DEBUG',
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
}
|
|
140
|
+
```
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AppConfig for Django-Q2 module with automatic schedule synchronization.
|
|
3
|
+
"""
|
|
4
|
+
import logging
|
|
5
|
+
from django.apps import AppConfig
|
|
6
|
+
from django.db.models.signals import post_migrate
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def sync_schedules_after_migrate(sender, **kwargs):
|
|
12
|
+
"""
|
|
13
|
+
Automatically sync Django-Q2 schedules after migrations.
|
|
14
|
+
|
|
15
|
+
This ensures schedules are always up-to-date after deployment.
|
|
16
|
+
Runs only once per migration cycle, safe from race conditions.
|
|
17
|
+
"""
|
|
18
|
+
# Only run for the django_cfg_django_q2 app itself
|
|
19
|
+
if sender.name != 'django_cfg.modules.django_q2':
|
|
20
|
+
return
|
|
21
|
+
|
|
22
|
+
# Import here to avoid circular imports and ensure Django is ready
|
|
23
|
+
try:
|
|
24
|
+
from django_q.models import Schedule
|
|
25
|
+
from django_cfg.core.config import get_current_config
|
|
26
|
+
except ImportError as e:
|
|
27
|
+
logger.warning(f"Could not import Django-Q2 dependencies: {e}")
|
|
28
|
+
return
|
|
29
|
+
|
|
30
|
+
config = get_current_config()
|
|
31
|
+
|
|
32
|
+
if not config or not hasattr(config, 'django_q2') or not config.django_q2 or not config.django_q2.enabled:
|
|
33
|
+
logger.debug("Django-Q2 not enabled, skipping schedule sync")
|
|
34
|
+
return
|
|
35
|
+
|
|
36
|
+
enabled_schedules = config.django_q2.get_enabled_schedules()
|
|
37
|
+
|
|
38
|
+
if not enabled_schedules:
|
|
39
|
+
logger.debug("No Django-Q2 schedules found in config")
|
|
40
|
+
return
|
|
41
|
+
|
|
42
|
+
logger.info(f"Syncing {len(enabled_schedules)} Django-Q2 schedule(s)...")
|
|
43
|
+
|
|
44
|
+
created = 0
|
|
45
|
+
updated = 0
|
|
46
|
+
|
|
47
|
+
for schedule_config in enabled_schedules:
|
|
48
|
+
schedule_dict = schedule_config.to_django_q_format()
|
|
49
|
+
name = schedule_dict['name']
|
|
50
|
+
|
|
51
|
+
try:
|
|
52
|
+
schedule, created_flag = Schedule.objects.update_or_create(
|
|
53
|
+
name=name,
|
|
54
|
+
defaults=schedule_dict
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
if created_flag:
|
|
58
|
+
created += 1
|
|
59
|
+
logger.info(f" ✓ Created schedule: {name}")
|
|
60
|
+
else:
|
|
61
|
+
updated += 1
|
|
62
|
+
logger.debug(f" ✓ Updated schedule: {name}")
|
|
63
|
+
|
|
64
|
+
except Exception as e:
|
|
65
|
+
logger.error(f" ✗ Failed to sync schedule '{name}': {e}")
|
|
66
|
+
|
|
67
|
+
logger.info(f"✅ Django-Q2 schedules synced: {created} created, {updated} updated")
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class DjangoQ2ModuleConfig(AppConfig):
|
|
71
|
+
"""
|
|
72
|
+
AppConfig for Django-Q2 module.
|
|
73
|
+
|
|
74
|
+
Automatically syncs schedules from config to database after migrations.
|
|
75
|
+
This eliminates the need for manual `sync_django_q_schedules` command.
|
|
76
|
+
|
|
77
|
+
Features:
|
|
78
|
+
- Automatic schedule sync after migrations
|
|
79
|
+
- Safe from race conditions (runs only once)
|
|
80
|
+
- Logs all sync operations
|
|
81
|
+
- Gracefully handles missing dependencies
|
|
82
|
+
|
|
83
|
+
Usage:
|
|
84
|
+
Add to INSTALLED_APPS:
|
|
85
|
+
INSTALLED_APPS = [
|
|
86
|
+
...
|
|
87
|
+
'django_cfg.modules.django_q2', # Auto-syncs schedules
|
|
88
|
+
]
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
default_auto_field = 'django.db.models.BigAutoField'
|
|
92
|
+
name = 'django_cfg.modules.django_q2'
|
|
93
|
+
verbose_name = 'Django-CFG Django-Q2 Module'
|
|
94
|
+
|
|
95
|
+
def ready(self):
|
|
96
|
+
"""
|
|
97
|
+
Connect post_migrate signal to automatically sync schedules.
|
|
98
|
+
|
|
99
|
+
This runs after all migrations are complete, ensuring:
|
|
100
|
+
1. Database tables exist
|
|
101
|
+
2. Config is loaded
|
|
102
|
+
3. Schedules are synced only once per migration cycle
|
|
103
|
+
"""
|
|
104
|
+
# Connect the signal
|
|
105
|
+
post_migrate.connect(sync_schedules_after_migrate, sender=self)
|
|
106
|
+
|
|
107
|
+
logger.debug(f"{self.verbose_name} initialized - auto-sync enabled")
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Management command to sync Django-Q2 schedules from config.
|
|
3
|
+
|
|
4
|
+
Usage:
|
|
5
|
+
python manage.py sync_django_q_schedules # Create/update schedules
|
|
6
|
+
python manage.py sync_django_q_schedules --dry-run # Show what would be created
|
|
7
|
+
"""
|
|
8
|
+
from django.core.management.base import BaseCommand
|
|
9
|
+
from django_q.models import Schedule
|
|
10
|
+
from django_cfg.core.config import get_current_config
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Command(BaseCommand):
|
|
14
|
+
help = 'Sync Django-Q2 schedules from config to database'
|
|
15
|
+
|
|
16
|
+
def add_arguments(self, parser):
|
|
17
|
+
parser.add_argument(
|
|
18
|
+
'--dry-run',
|
|
19
|
+
action='store_true',
|
|
20
|
+
help='Show what would be created without actually creating',
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
def handle(self, *args, **options):
|
|
24
|
+
config = get_current_config()
|
|
25
|
+
|
|
26
|
+
if not config:
|
|
27
|
+
self.stdout.write(self.style.ERROR('❌ No config found'))
|
|
28
|
+
return
|
|
29
|
+
|
|
30
|
+
# Check if Django-Q2 is enabled
|
|
31
|
+
if not hasattr(config, 'django_q2') or not config.django_q2 or not config.django_q2.enabled:
|
|
32
|
+
self.stdout.write(self.style.WARNING('⚠️ Django-Q2 is not enabled in config'))
|
|
33
|
+
return
|
|
34
|
+
|
|
35
|
+
enabled_schedules = config.django_q2.get_enabled_schedules()
|
|
36
|
+
|
|
37
|
+
if not enabled_schedules:
|
|
38
|
+
self.stdout.write(self.style.WARNING('⚠️ No schedules found in config'))
|
|
39
|
+
return
|
|
40
|
+
|
|
41
|
+
self.stdout.write(f'📋 Found {len(enabled_schedules)} schedule(s) in config\n')
|
|
42
|
+
|
|
43
|
+
created = 0
|
|
44
|
+
updated = 0
|
|
45
|
+
|
|
46
|
+
for schedule_config in enabled_schedules:
|
|
47
|
+
schedule_dict = schedule_config.to_django_q_format()
|
|
48
|
+
name = schedule_dict['name']
|
|
49
|
+
|
|
50
|
+
if options['dry_run']:
|
|
51
|
+
self.stdout.write(f' [DRY RUN] Would create/update: {name}')
|
|
52
|
+
continue
|
|
53
|
+
|
|
54
|
+
# Update or create schedule
|
|
55
|
+
schedule, created_flag = Schedule.objects.update_or_create(
|
|
56
|
+
name=name,
|
|
57
|
+
defaults=schedule_dict
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
if created_flag:
|
|
61
|
+
created += 1
|
|
62
|
+
self.stdout.write(self.style.SUCCESS(f' ✓ Created: {name}'))
|
|
63
|
+
else:
|
|
64
|
+
updated += 1
|
|
65
|
+
self.stdout.write(self.style.SUCCESS(f' ✓ Updated: {name}'))
|
|
66
|
+
|
|
67
|
+
if not options['dry_run']:
|
|
68
|
+
self.stdout.write(self.style.SUCCESS(
|
|
69
|
+
f'\n✅ Summary: {created} created, {updated} updated'
|
|
70
|
+
))
|
|
71
|
+
else:
|
|
72
|
+
self.stdout.write(self.style.WARNING(
|
|
73
|
+
f'\n[DRY RUN] Would create {len(enabled_schedules)} schedule(s)'
|
|
74
|
+
))
|
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.
|
|
7
|
+
version = "1.4.118"
|
|
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-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)", "
|
|
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)", "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"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: django-cfg
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.118
|
|
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
|
|
@@ -71,7 +71,6 @@ Requires-Dist: pydantic<3.0,>=2.11.0
|
|
|
71
71
|
Requires-Dist: pydantic[email]<3.0,>=2.11.0
|
|
72
72
|
Requires-Dist: pytelegrambotapi<5.0,>=4.28.0
|
|
73
73
|
Requires-Dist: python-json-logger<4.0,>=3.3.0
|
|
74
|
-
Requires-Dist: pytz>=2025.1
|
|
75
74
|
Requires-Dist: pyyaml<7.0,>=6.0
|
|
76
75
|
Requires-Dist: questionary<3.0,>=2.1.0
|
|
77
76
|
Requires-Dist: rearq<1.0,>=0.2.0
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
django_cfg/README.md,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
django_cfg/__init__.py,sha256=
|
|
2
|
+
django_cfg/__init__.py,sha256=czBPTVeDvyLUMK-04V3RRLhBFzXwK7DP_dDyzQq7ZNw,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
|
|
@@ -544,7 +544,7 @@ django_cfg/core/backends/smtp.py,sha256=kWkNMG7UwLsHcFYSKRgrk1HbP9mU1fxzWYnalHXq
|
|
|
544
544
|
django_cfg/core/base/__init__.py,sha256=Z3bZvxejxk4vvWqmqTBLUi9XJpo6A_5Bq4R0J8q81Y4,116
|
|
545
545
|
django_cfg/core/base/config_model.py,sha256=fnmvjOs2fHTb8ifjFv0EsbVPFScG87ExikIqVAqpDZc,21810
|
|
546
546
|
django_cfg/core/builders/__init__.py,sha256=jkInI7_jbxcjitapohw6QmbJPpacnnID6V1JovqtOFM,282
|
|
547
|
-
django_cfg/core/builders/apps_builder.py,sha256=
|
|
547
|
+
django_cfg/core/builders/apps_builder.py,sha256=1C7M3Uq4aScuz4syuNGHyl3USus1h_FgULPfzKAerak,6810
|
|
548
548
|
django_cfg/core/builders/middleware_builder.py,sha256=OwqQRoJKYWlXsQNPFBfUvVMYdppUHCPw-UDczV_esYg,3101
|
|
549
549
|
django_cfg/core/builders/security_builder.py,sha256=W8Lk9eTMi3PuNK5qH-BIHegeE0cbvmuHKTumLcwOAh8,23961
|
|
550
550
|
django_cfg/core/environment/__init__.py,sha256=sMOIe9z1i51j8B1VGjpLHJMaeDsBfsgn1TmL03FIeNo,141
|
|
@@ -644,7 +644,7 @@ django_cfg/models/django/__init__.py,sha256=J4VRl77vgXzfKcdUcX-sPxpBSOJ4qA-8RstP
|
|
|
644
644
|
django_cfg/models/django/axes.py,sha256=-4nk2gSfpj7lNY5vnm_2jHVLz8VAKoEd9yF2TuCR8O8,5624
|
|
645
645
|
django_cfg/models/django/constance.py,sha256=6x57bi40mDX0fKcKeQKgV2BO3WIVYPQllAchWsj4KvM,8847
|
|
646
646
|
django_cfg/models/django/crypto_fields.py,sha256=OguITidM4Mp564p_gbsokeNCZxjL9hrK1Vw0McuA3yo,4700
|
|
647
|
-
django_cfg/models/django/django_q2.py,sha256=
|
|
647
|
+
django_cfg/models/django/django_q2.py,sha256=G8m2hg0-IE-GLsGabaHetGVdbb_cNas8RCbZBBr-xz4,15564
|
|
648
648
|
django_cfg/models/django/environment.py,sha256=lBCHBs1lphv9tlu1BCTfLZeH_kUame0p66A_BIjBY7M,9440
|
|
649
649
|
django_cfg/models/django/openapi.py,sha256=avE3iapaCj8eyOqVUum_v2EExR3V-hwHrexqtXMHtTQ,3739
|
|
650
650
|
django_cfg/models/django/revolution_legacy.py,sha256=Z4SPUS7QSv62EuPAeFFoXGEgqLmdXnVEr7Ofk1IDtVc,8918
|
|
@@ -947,6 +947,12 @@ django_cfg/modules/django_ngrok/service.py,sha256=Xkh9Gl6Rth32UcT0UYjD0ckROHFw6F
|
|
|
947
947
|
django_cfg/modules/django_ngrok/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
948
948
|
django_cfg/modules/django_ngrok/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
949
949
|
django_cfg/modules/django_ngrok/management/commands/runserver_ngrok.py,sha256=urwO1nPjcBMPn7k8WXBzfWQpjzCsIKaiET2Gf5afYwk,6259
|
|
950
|
+
django_cfg/modules/django_q2/README.md,sha256=pyY0EqefXTJ47k_liMv22d0zx-9dHVPGFUSZS3aLQjE,4763
|
|
951
|
+
django_cfg/modules/django_q2/__init__.py,sha256=6Eu26O-4ddwE8qO27pTT6x13-iPc9eA2Pzq8_cRHZMc,186
|
|
952
|
+
django_cfg/modules/django_q2/apps.py,sha256=UoSbow-Wlkwriem5mEud1vrUD7_TnqANMzoajGLBVQs,3396
|
|
953
|
+
django_cfg/modules/django_q2/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
954
|
+
django_cfg/modules/django_q2/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
955
|
+
django_cfg/modules/django_q2/management/commands/sync_django_q_schedules.py,sha256=ik_4kmKp9RUTOaxewWK6KgwK_1_1wJcVZQ2LAdSG0Lo,2671
|
|
950
956
|
django_cfg/modules/django_tailwind/README.md,sha256=tPQd4ir79MLFSVUKBGfPAF22LZWE0BcmzcNdQhJ4k7I,10804
|
|
951
957
|
django_cfg/modules/django_tailwind/__init__.py,sha256=K0GbFxjemNixRUgexurSTDfN4kB--TmuFCk9n5DbLYc,186
|
|
952
958
|
django_cfg/modules/django_tailwind/apps.py,sha256=CKNd0xDoLaQpe7SEfay0ZtWkjLUVRgofkB8FobKLXV8,313
|
|
@@ -1060,9 +1066,9 @@ django_cfg/utils/version_check.py,sha256=WO51J2m2e-wVqWCRwbultEwu3q1lQasV67Mw2aa
|
|
|
1060
1066
|
django_cfg/CHANGELOG.md,sha256=jtT3EprqEJkqSUh7IraP73vQ8PmKUMdRtznQsEnqDZk,2052
|
|
1061
1067
|
django_cfg/CONTRIBUTING.md,sha256=DU2kyQ6PU0Z24ob7O_OqKWEYHcZmJDgzw-lQCmu6uBg,3041
|
|
1062
1068
|
django_cfg/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
|
|
1063
|
-
django_cfg/pyproject.toml,sha256=
|
|
1064
|
-
django_cfg-1.4.
|
|
1065
|
-
django_cfg-1.4.
|
|
1066
|
-
django_cfg-1.4.
|
|
1067
|
-
django_cfg-1.4.
|
|
1068
|
-
django_cfg-1.4.
|
|
1069
|
+
django_cfg/pyproject.toml,sha256=fZ9FGyvoUZbCwaNqWJDQwUNYeN11UYgds7UsrzwGFO0,8665
|
|
1070
|
+
django_cfg-1.4.118.dist-info/METADATA,sha256=NcD294dwA8ckrblk-0er6UcqtHdYYren4RsZh77BqkU,23876
|
|
1071
|
+
django_cfg-1.4.118.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
1072
|
+
django_cfg-1.4.118.dist-info/entry_points.txt,sha256=Ucmde4Z2wEzgb4AggxxZ0zaYDb9HpyE5blM3uJ0_VNg,56
|
|
1073
|
+
django_cfg-1.4.118.dist-info/licenses/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
|
|
1074
|
+
django_cfg-1.4.118.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|