django-cfg 1.2.15__py3-none-any.whl → 1.2.17__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.
- django_cfg/__init__.py +1 -1
- django_cfg/apps/maintenance/README.md +305 -0
- django_cfg/apps/maintenance/__init__.py +27 -0
- django_cfg/apps/maintenance/admin/__init__.py +28 -0
- django_cfg/apps/maintenance/admin/deployments_admin.py +251 -0
- django_cfg/apps/maintenance/admin/events_admin.py +374 -0
- django_cfg/apps/maintenance/admin/monitoring_admin.py +215 -0
- django_cfg/apps/maintenance/admin/sites_admin.py +464 -0
- django_cfg/apps/maintenance/apps.py +105 -0
- django_cfg/apps/maintenance/management/__init__.py +0 -0
- django_cfg/apps/maintenance/management/commands/__init__.py +0 -0
- django_cfg/apps/maintenance/management/commands/maintenance.py +375 -0
- django_cfg/apps/maintenance/management/commands/sync_cloudflare.py +168 -0
- django_cfg/apps/maintenance/managers/__init__.py +20 -0
- django_cfg/apps/maintenance/managers/deployments.py +287 -0
- django_cfg/apps/maintenance/managers/events.py +374 -0
- django_cfg/apps/maintenance/managers/monitoring.py +301 -0
- django_cfg/apps/maintenance/managers/sites.py +335 -0
- django_cfg/apps/maintenance/migrations/0001_initial.py +939 -0
- django_cfg/apps/maintenance/migrations/__init__.py +0 -0
- django_cfg/apps/maintenance/models/__init__.py +27 -0
- django_cfg/apps/maintenance/models/cloudflare.py +316 -0
- django_cfg/apps/maintenance/models/maintenance.py +334 -0
- django_cfg/apps/maintenance/models/monitoring.py +393 -0
- django_cfg/apps/maintenance/models/sites.py +419 -0
- django_cfg/apps/maintenance/serializers/__init__.py +60 -0
- django_cfg/apps/maintenance/serializers/actions.py +310 -0
- django_cfg/apps/maintenance/serializers/base.py +44 -0
- django_cfg/apps/maintenance/serializers/deployments.py +209 -0
- django_cfg/apps/maintenance/serializers/events.py +210 -0
- django_cfg/apps/maintenance/serializers/monitoring.py +278 -0
- django_cfg/apps/maintenance/serializers/sites.py +213 -0
- django_cfg/apps/maintenance/services/README.md +168 -0
- django_cfg/apps/maintenance/services/__init__.py +21 -0
- django_cfg/apps/maintenance/services/cloudflare_client.py +441 -0
- django_cfg/apps/maintenance/services/dns_manager.py +497 -0
- django_cfg/apps/maintenance/services/maintenance_manager.py +504 -0
- django_cfg/apps/maintenance/services/site_sync.py +448 -0
- django_cfg/apps/maintenance/services/sync_command_service.py +330 -0
- django_cfg/apps/maintenance/services/worker_manager.py +264 -0
- django_cfg/apps/maintenance/signals.py +38 -0
- django_cfg/apps/maintenance/urls.py +36 -0
- django_cfg/apps/maintenance/views/__init__.py +18 -0
- django_cfg/apps/maintenance/views/base.py +61 -0
- django_cfg/apps/maintenance/views/deployments.py +175 -0
- django_cfg/apps/maintenance/views/events.py +204 -0
- django_cfg/apps/maintenance/views/monitoring.py +213 -0
- django_cfg/apps/maintenance/views/sites.py +338 -0
- django_cfg/apps/urls.py +5 -1
- django_cfg/core/config.py +34 -3
- django_cfg/core/generation.py +15 -10
- django_cfg/models/cloudflare.py +316 -0
- django_cfg/models/revolution.py +1 -1
- django_cfg/models/tasks.py +1 -1
- django_cfg/modules/base.py +12 -5
- django_cfg/modules/django_unfold/dashboard.py +16 -1
- {django_cfg-1.2.15.dist-info → django_cfg-1.2.17.dist-info}/METADATA +2 -1
- {django_cfg-1.2.15.dist-info → django_cfg-1.2.17.dist-info}/RECORD +61 -13
- {django_cfg-1.2.15.dist-info → django_cfg-1.2.17.dist-info}/WHEEL +0 -0
- {django_cfg-1.2.15.dist-info → django_cfg-1.2.17.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.2.15.dist-info → django_cfg-1.2.17.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,338 @@
|
|
1
|
+
"""
|
2
|
+
Site management views.
|
3
|
+
|
4
|
+
ViewSets for CloudflareSite and SiteGroup management.
|
5
|
+
"""
|
6
|
+
|
7
|
+
import logging
|
8
|
+
from datetime import datetime
|
9
|
+
|
10
|
+
from django.shortcuts import get_object_or_404
|
11
|
+
from rest_framework import viewsets, status
|
12
|
+
from rest_framework.decorators import action
|
13
|
+
from drf_spectacular.utils import (
|
14
|
+
extend_schema, extend_schema_view, OpenApiResponse, OpenApiParameter, OpenApiTypes
|
15
|
+
)
|
16
|
+
|
17
|
+
from ..models import CloudflareSite, SiteGroup
|
18
|
+
from ..serializers import (
|
19
|
+
CloudflareSiteSerializer, CloudflareSiteCreateSerializer, CloudflareSiteListSerializer,
|
20
|
+
SiteGroupSerializer, SiteGroupCreateSerializer,
|
21
|
+
BulkMaintenanceActionSerializer, APIResponseSerializer
|
22
|
+
)
|
23
|
+
from ..services import MaintenanceManager
|
24
|
+
from .base import MaintenancePermissionMixin, MaintenanceResponseMixin
|
25
|
+
|
26
|
+
logger = logging.getLogger(__name__)
|
27
|
+
|
28
|
+
|
29
|
+
@extend_schema_view(
|
30
|
+
list=extend_schema(
|
31
|
+
summary="List Cloudflare sites",
|
32
|
+
description="Get list of Cloudflare sites with filtering options",
|
33
|
+
parameters=[
|
34
|
+
OpenApiParameter('environment', OpenApiTypes.STR, description='Filter by environment'),
|
35
|
+
OpenApiParameter('project', OpenApiTypes.STR, description='Filter by project'),
|
36
|
+
OpenApiParameter('status', OpenApiTypes.STR, description='Filter by status'),
|
37
|
+
OpenApiParameter('maintenance_active', OpenApiTypes.BOOL, description='Filter by maintenance status'),
|
38
|
+
OpenApiParameter('search', OpenApiTypes.STR, description='Search in name and domain'),
|
39
|
+
]
|
40
|
+
),
|
41
|
+
create=extend_schema(
|
42
|
+
summary="Create Cloudflare site",
|
43
|
+
description="Create a new Cloudflare site configuration"
|
44
|
+
),
|
45
|
+
retrieve=extend_schema(
|
46
|
+
summary="Get Cloudflare site",
|
47
|
+
description="Get detailed information about a specific Cloudflare site"
|
48
|
+
),
|
49
|
+
update=extend_schema(
|
50
|
+
summary="Update Cloudflare site",
|
51
|
+
description="Update Cloudflare site configuration"
|
52
|
+
),
|
53
|
+
destroy=extend_schema(
|
54
|
+
summary="Delete Cloudflare site",
|
55
|
+
description="Delete a Cloudflare site configuration"
|
56
|
+
)
|
57
|
+
)
|
58
|
+
class CloudflareSiteViewSet(MaintenancePermissionMixin, MaintenanceResponseMixin, viewsets.ModelViewSet):
|
59
|
+
"""ViewSet for managing Cloudflare sites."""
|
60
|
+
|
61
|
+
serializer_class = CloudflareSiteSerializer
|
62
|
+
lookup_field = 'id'
|
63
|
+
filterset_fields = ['environment', 'project', 'current_status', 'maintenance_active']
|
64
|
+
search_fields = ['name', 'domain', 'project']
|
65
|
+
ordering_fields = ['name', 'domain', 'created_at', 'last_maintenance_at']
|
66
|
+
ordering = ['-created_at']
|
67
|
+
|
68
|
+
def get_queryset(self):
|
69
|
+
"""Get queryset filtered by user permissions."""
|
70
|
+
return self.get_user_queryset(CloudflareSite)
|
71
|
+
|
72
|
+
def get_serializer_class(self):
|
73
|
+
"""Return appropriate serializer based on action."""
|
74
|
+
if self.action == 'create':
|
75
|
+
return CloudflareSiteCreateSerializer
|
76
|
+
elif self.action == 'list':
|
77
|
+
return CloudflareSiteListSerializer
|
78
|
+
elif self.action == 'bulk_action':
|
79
|
+
return BulkMaintenanceActionSerializer
|
80
|
+
return CloudflareSiteSerializer
|
81
|
+
|
82
|
+
def perform_create(self, serializer):
|
83
|
+
"""Set owner when creating site."""
|
84
|
+
serializer.save(owner=self.request.user)
|
85
|
+
|
86
|
+
@action(detail=True, methods=['post'])
|
87
|
+
@extend_schema(
|
88
|
+
summary="Enable maintenance mode",
|
89
|
+
description="Enable maintenance mode for this site",
|
90
|
+
request=None,
|
91
|
+
responses={
|
92
|
+
200: OpenApiResponse(response=APIResponseSerializer, description="Maintenance enabled successfully"),
|
93
|
+
400: OpenApiResponse(response=APIResponseSerializer, description="Bad request"),
|
94
|
+
500: OpenApiResponse(response=APIResponseSerializer, description="Internal server error")
|
95
|
+
}
|
96
|
+
)
|
97
|
+
def enable_maintenance(self, request, id=None):
|
98
|
+
"""Enable maintenance mode for a site."""
|
99
|
+
try:
|
100
|
+
site = self.get_object()
|
101
|
+
reason = request.data.get('reason', 'Manual maintenance')
|
102
|
+
message = request.data.get('message', 'Site is under maintenance')
|
103
|
+
|
104
|
+
# Use multi-site manager for consistency
|
105
|
+
manager = MaintenanceManager(self.request.user)
|
106
|
+
success = manager._enable_site_maintenance(site, reason, message)
|
107
|
+
|
108
|
+
if success:
|
109
|
+
return self.success_response(f'Maintenance enabled for {site.domain}')
|
110
|
+
else:
|
111
|
+
return self.error_response('Failed to enable maintenance mode')
|
112
|
+
|
113
|
+
except Exception as e:
|
114
|
+
return self.error_response(f"Enable maintenance error for site {id}: {e}")
|
115
|
+
|
116
|
+
@action(detail=True, methods=['post'])
|
117
|
+
@extend_schema(
|
118
|
+
summary="Disable maintenance mode",
|
119
|
+
description="Disable maintenance mode for this site",
|
120
|
+
responses={
|
121
|
+
200: OpenApiResponse(response=APIResponseSerializer, description="Maintenance disabled successfully"),
|
122
|
+
500: OpenApiResponse(response=APIResponseSerializer, description="Internal server error")
|
123
|
+
}
|
124
|
+
)
|
125
|
+
def disable_maintenance(self, request, id=None):
|
126
|
+
"""Disable maintenance mode for a site."""
|
127
|
+
try:
|
128
|
+
site = self.get_object()
|
129
|
+
|
130
|
+
# Use multi-site manager for consistency
|
131
|
+
manager = MaintenanceManager(self.request.user)
|
132
|
+
success = manager._disable_site_maintenance(site)
|
133
|
+
|
134
|
+
if success:
|
135
|
+
return self.success_response(f'Maintenance disabled for {site.domain}')
|
136
|
+
else:
|
137
|
+
return self.error_response('Failed to disable maintenance mode')
|
138
|
+
|
139
|
+
except Exception as e:
|
140
|
+
return self.error_response(f"Disable maintenance error for site {id}: {e}")
|
141
|
+
|
142
|
+
@action(detail=True, methods=['get'])
|
143
|
+
@extend_schema(
|
144
|
+
summary="Check site status",
|
145
|
+
description="Check current status of the site",
|
146
|
+
responses={
|
147
|
+
200: OpenApiResponse(response=APIResponseSerializer, description="Status checked successfully")
|
148
|
+
}
|
149
|
+
)
|
150
|
+
def check_status(self, request, id=None):
|
151
|
+
"""Check current status of a site."""
|
152
|
+
try:
|
153
|
+
site = self.get_object()
|
154
|
+
|
155
|
+
# Use multi-site manager for consistency
|
156
|
+
manager = MaintenanceManager(self.request.user)
|
157
|
+
site_status = manager._check_site_status(site)
|
158
|
+
|
159
|
+
return self.success_response(
|
160
|
+
'Status checked successfully',
|
161
|
+
data={
|
162
|
+
'site_id': site.id,
|
163
|
+
'domain': site.domain,
|
164
|
+
'status': site_status,
|
165
|
+
'maintenance_active': site.maintenance_active,
|
166
|
+
'last_check': datetime.now().isoformat()
|
167
|
+
}
|
168
|
+
)
|
169
|
+
|
170
|
+
except Exception as e:
|
171
|
+
return self.error_response(f"Status check error for site {id}: {e}")
|
172
|
+
|
173
|
+
@action(detail=False, methods=['post'])
|
174
|
+
@extend_schema(
|
175
|
+
summary="Bulk maintenance actions",
|
176
|
+
description="Perform bulk maintenance actions on multiple sites",
|
177
|
+
request=BulkMaintenanceActionSerializer,
|
178
|
+
responses={
|
179
|
+
200: OpenApiResponse(response=APIResponseSerializer, description="Bulk action completed"),
|
180
|
+
400: OpenApiResponse(response=APIResponseSerializer, description="Invalid request data")
|
181
|
+
}
|
182
|
+
)
|
183
|
+
def bulk_action(self, request):
|
184
|
+
"""Perform bulk maintenance actions."""
|
185
|
+
serializer = BulkMaintenanceActionSerializer(data=request.data)
|
186
|
+
if not serializer.is_valid():
|
187
|
+
return self.validation_error_response(serializer.errors)
|
188
|
+
|
189
|
+
try:
|
190
|
+
action_type = serializer.validated_data['action']
|
191
|
+
site_ids = serializer.validated_data['site_ids']
|
192
|
+
dry_run = serializer.validated_data.get('dry_run', False)
|
193
|
+
|
194
|
+
# Get sites (filtered by user permissions)
|
195
|
+
sites = self.get_queryset().filter(id__in=site_ids)
|
196
|
+
|
197
|
+
if dry_run:
|
198
|
+
return self.success_response(
|
199
|
+
f'Dry run: would {action_type} maintenance for {sites.count()} sites',
|
200
|
+
data={
|
201
|
+
'dry_run': True,
|
202
|
+
'would_affect': [site.domain for site in sites]
|
203
|
+
}
|
204
|
+
)
|
205
|
+
|
206
|
+
# Use multi-site manager for bulk operations
|
207
|
+
manager = MaintenanceManager(self.request.user).sites(request.user).filter(id__in=site_ids)
|
208
|
+
|
209
|
+
if action_type == 'enable':
|
210
|
+
reason = serializer.validated_data.get('reason', 'Bulk maintenance')
|
211
|
+
result = manager.enable_maintenance(
|
212
|
+
reason=reason,
|
213
|
+
user=request.user,
|
214
|
+
message=serializer.validated_data.get('maintenance_message')
|
215
|
+
)
|
216
|
+
elif action_type == 'disable':
|
217
|
+
result = manager.disable_maintenance(user=request.user)
|
218
|
+
elif action_type == 'status_check':
|
219
|
+
result = manager.check_status()
|
220
|
+
else:
|
221
|
+
return self.error_response(f'Unknown action: {action_type}', status.HTTP_400_BAD_REQUEST)
|
222
|
+
|
223
|
+
return self.success_response(f'Bulk {action_type} completed', data=result)
|
224
|
+
|
225
|
+
except Exception as e:
|
226
|
+
return self.error_response(f"Bulk action error: {e}")
|
227
|
+
|
228
|
+
|
229
|
+
@extend_schema_view(
|
230
|
+
list=extend_schema(
|
231
|
+
summary="List site groups",
|
232
|
+
description="Get list of site groups"
|
233
|
+
),
|
234
|
+
create=extend_schema(
|
235
|
+
summary="Create site group",
|
236
|
+
description="Create a new site group"
|
237
|
+
)
|
238
|
+
)
|
239
|
+
class SiteGroupViewSet(MaintenancePermissionMixin, MaintenanceResponseMixin, viewsets.ModelViewSet):
|
240
|
+
"""ViewSet for managing site groups."""
|
241
|
+
|
242
|
+
serializer_class = SiteGroupSerializer
|
243
|
+
lookup_field = 'id'
|
244
|
+
|
245
|
+
def get_queryset(self):
|
246
|
+
"""Get queryset filtered by user permissions."""
|
247
|
+
return self.get_user_queryset(SiteGroup)
|
248
|
+
|
249
|
+
def get_serializer_class(self):
|
250
|
+
"""Return appropriate serializer based on action."""
|
251
|
+
if self.action == 'create':
|
252
|
+
return SiteGroupCreateSerializer
|
253
|
+
return SiteGroupSerializer
|
254
|
+
|
255
|
+
def perform_create(self, serializer):
|
256
|
+
"""Set owner when creating group."""
|
257
|
+
serializer.save(owner=self.request.user)
|
258
|
+
|
259
|
+
@action(detail=True, methods=['post'])
|
260
|
+
@extend_schema(
|
261
|
+
summary="Add sites to group",
|
262
|
+
description="Add sites to this group"
|
263
|
+
)
|
264
|
+
def add_sites(self, request, id=None):
|
265
|
+
"""Add sites to group."""
|
266
|
+
try:
|
267
|
+
group = self.get_object()
|
268
|
+
site_ids = request.data.get('site_ids', [])
|
269
|
+
|
270
|
+
# Get sites (filtered by user permissions)
|
271
|
+
sites = self.get_user_queryset(CloudflareSite).filter(id__in=site_ids)
|
272
|
+
group.sites.add(*sites)
|
273
|
+
|
274
|
+
return self.success_response(f'Added {sites.count()} sites to group {group.name}')
|
275
|
+
|
276
|
+
except Exception as e:
|
277
|
+
return self.error_response(f"Add sites to group error: {e}")
|
278
|
+
|
279
|
+
@action(detail=True, methods=['post'])
|
280
|
+
@extend_schema(
|
281
|
+
summary="Remove sites from group",
|
282
|
+
description="Remove sites from this group"
|
283
|
+
)
|
284
|
+
def remove_sites(self, request, id=None):
|
285
|
+
"""Remove sites from group."""
|
286
|
+
try:
|
287
|
+
group = self.get_object()
|
288
|
+
site_ids = request.data.get('site_ids', [])
|
289
|
+
|
290
|
+
# Get sites (filtered by user permissions)
|
291
|
+
sites = self.get_user_queryset(CloudflareSite).filter(id__in=site_ids)
|
292
|
+
group.sites.remove(*sites)
|
293
|
+
|
294
|
+
return self.success_response(f'Removed {sites.count()} sites from group {group.name}')
|
295
|
+
|
296
|
+
except Exception as e:
|
297
|
+
return self.error_response(f"Remove sites from group error: {e}")
|
298
|
+
|
299
|
+
@action(detail=True, methods=['post'])
|
300
|
+
@extend_schema(
|
301
|
+
summary="Enable maintenance for group",
|
302
|
+
description="Enable maintenance mode for all sites in this group"
|
303
|
+
)
|
304
|
+
def enable_maintenance(self, request, id=None):
|
305
|
+
"""Enable maintenance for all sites in group."""
|
306
|
+
try:
|
307
|
+
group = self.get_object()
|
308
|
+
reason = request.data.get('reason', f'Group maintenance: {group.name}')
|
309
|
+
|
310
|
+
result = group.enable_maintenance_for_all(request.user, reason)
|
311
|
+
|
312
|
+
return self.success_response(
|
313
|
+
f'Group maintenance enabled for {group.name}',
|
314
|
+
data=result
|
315
|
+
)
|
316
|
+
|
317
|
+
except Exception as e:
|
318
|
+
return self.error_response(f"Group maintenance enable error: {e}")
|
319
|
+
|
320
|
+
@action(detail=True, methods=['post'])
|
321
|
+
@extend_schema(
|
322
|
+
summary="Disable maintenance for group",
|
323
|
+
description="Disable maintenance mode for all sites in this group"
|
324
|
+
)
|
325
|
+
def disable_maintenance(self, request, id=None):
|
326
|
+
"""Disable maintenance for all sites in group."""
|
327
|
+
try:
|
328
|
+
group = self.get_object()
|
329
|
+
|
330
|
+
result = group.disable_maintenance_for_all()
|
331
|
+
|
332
|
+
return self.success_response(
|
333
|
+
f'Group maintenance disabled for {group.name}',
|
334
|
+
data=result
|
335
|
+
)
|
336
|
+
|
337
|
+
except Exception as e:
|
338
|
+
return self.error_response(f"Group maintenance disable error: {e}")
|
django_cfg/apps/urls.py
CHANGED
@@ -45,8 +45,12 @@ def get_django_cfg_urlpatterns() -> List[URLPattern]:
|
|
45
45
|
# patterns.append(path('leads/', include('django_cfg.apps.leads.urls')))
|
46
46
|
|
47
47
|
# Tasks app - enabled when knowbase or agents are enabled
|
48
|
-
if base_module.
|
48
|
+
if base_module.should_enable_tasks():
|
49
49
|
patterns.append(path('tasks/', include('django_cfg.apps.tasks.urls')))
|
50
|
+
|
51
|
+
# Maintenance app - multi-site maintenance mode with Cloudflare
|
52
|
+
if base_module.is_maintenance_enabled():
|
53
|
+
patterns.append(path('maintenance/', include('django_cfg.apps.maintenance.urls')))
|
50
54
|
|
51
55
|
except Exception:
|
52
56
|
# Fallback: include all URLs if config is not available
|
django_cfg/core/config.py
CHANGED
@@ -58,7 +58,7 @@ DEFAULT_APPS = [
|
|
58
58
|
"django_extensions",
|
59
59
|
"constance",
|
60
60
|
"constance.backends.database",
|
61
|
-
|
61
|
+
# Note: django_dramatiq is added conditionally when tasks are enabled
|
62
62
|
# Django CFG
|
63
63
|
"django_cfg",
|
64
64
|
"django_revolution",
|
@@ -270,6 +270,12 @@ class DjangoConfig(BaseModel):
|
|
270
270
|
description="Application limits configuration (file uploads, requests, etc.)",
|
271
271
|
)
|
272
272
|
|
273
|
+
# === Maintenance Mode Configuration ===
|
274
|
+
enable_maintenance: bool = Field(
|
275
|
+
default=False,
|
276
|
+
description="Enable django-cfg Maintenance application (multi-site maintenance mode with Cloudflare)",
|
277
|
+
)
|
278
|
+
|
273
279
|
# === Middleware Configuration ===
|
274
280
|
custom_middleware: List[str] = Field(
|
275
281
|
default_factory=list,
|
@@ -518,6 +524,28 @@ class DjangoConfig(BaseModel):
|
|
518
524
|
code=otp_code
|
519
525
|
)
|
520
526
|
|
527
|
+
def should_enable_tasks(self) -> bool:
|
528
|
+
"""
|
529
|
+
Determine if background tasks should be enabled.
|
530
|
+
|
531
|
+
Tasks are enabled if:
|
532
|
+
1. Explicitly configured via tasks field
|
533
|
+
2. Knowledge base is enabled (requires background processing)
|
534
|
+
3. Agents are enabled (requires background processing)
|
535
|
+
|
536
|
+
Returns:
|
537
|
+
True if tasks should be enabled, False otherwise
|
538
|
+
"""
|
539
|
+
# Check if explicitly configured
|
540
|
+
if hasattr(self, 'tasks') and self.tasks and self.tasks.enabled:
|
541
|
+
return True
|
542
|
+
|
543
|
+
# Check if features that require tasks are enabled
|
544
|
+
if self.enable_knowbase or self.enable_agents:
|
545
|
+
return True
|
546
|
+
|
547
|
+
return False
|
548
|
+
|
521
549
|
def get_installed_apps(self) -> List[str]:
|
522
550
|
"""
|
523
551
|
Get complete list of installed Django apps.
|
@@ -547,9 +575,12 @@ class DjangoConfig(BaseModel):
|
|
547
575
|
apps.append("django_cfg.apps.knowbase")
|
548
576
|
if self.enable_agents:
|
549
577
|
apps.append("django_cfg.apps.agents")
|
578
|
+
if self.enable_maintenance:
|
579
|
+
apps.append("django_cfg.apps.maintenance")
|
550
580
|
|
551
|
-
# Auto-enable tasks if
|
552
|
-
if self.
|
581
|
+
# Auto-enable tasks if needed
|
582
|
+
if self.should_enable_tasks():
|
583
|
+
apps.append("django_dramatiq") # Add django_dramatiq first
|
553
584
|
apps.append("django_cfg.apps.tasks")
|
554
585
|
|
555
586
|
# Auto-detect dashboard apps from Unfold callback
|
django_cfg/core/generation.py
CHANGED
@@ -418,16 +418,21 @@ class SettingsGenerator:
|
|
418
418
|
|
419
419
|
# Check for Tasks/Dramatiq configuration
|
420
420
|
try:
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
if
|
429
|
-
|
430
|
-
|
421
|
+
# Use the config's computed method to determine if tasks should be enabled
|
422
|
+
if config.should_enable_tasks():
|
423
|
+
from django_cfg.models.tasks import TaskConfig
|
424
|
+
from django_cfg.modules.django_tasks import generate_dramatiq_settings_from_config
|
425
|
+
|
426
|
+
# Auto-initialize TaskConfig if needed and generate settings
|
427
|
+
task_config = TaskConfig.auto_initialize_if_needed()
|
428
|
+
if task_config is not None:
|
429
|
+
dramatiq_settings = generate_dramatiq_settings_from_config()
|
430
|
+
if dramatiq_settings:
|
431
|
+
settings.update(dramatiq_settings)
|
432
|
+
integrations.append("dramatiq")
|
433
|
+
logger.info("✅ Dramatiq enabled (tasks/knowbase/agents required)")
|
434
|
+
else:
|
435
|
+
logger.debug("⏭️ Dramatiq disabled (no tasks/knowbase/agents)")
|
431
436
|
|
432
437
|
except ImportError as e:
|
433
438
|
logger.warning(f"Failed to import django_tasks module: {e}")
|