django-cfg 1.4.9__py3-none-any.whl → 1.4.10__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/apps/payments/middleware/api_access.py +6 -2
- django_cfg/apps/payments/middleware/rate_limiting.py +2 -1
- django_cfg/apps/payments/middleware/usage_tracking.py +5 -1
- django_cfg/apps/payments/models/managers/api_key_managers.py +0 -1
- django_cfg/apps/payments/models/managers/subscription_managers.py +0 -1
- django_cfg/apps/payments/services/core/balance_service.py +5 -5
- django_cfg/apps/payments/services/core/subscription_service.py +1 -2
- django_cfg/apps/payments/views/api/balances.py +8 -7
- django_cfg/apps/payments/views/api/base.py +10 -6
- django_cfg/apps/payments/views/api/currencies.py +4 -4
- django_cfg/apps/payments/views/api/payments.py +3 -1
- django_cfg/apps/payments/views/api/subscriptions.py +2 -5
- django_cfg/core/generation/integration_generators/api.py +19 -1
- django_cfg/management/commands/check_settings.py +84 -1
- django_cfg/models/django/revolution.py +8 -0
- django_cfg/modules/django_unfold/dashboard.py +1 -1
- django_cfg/pyproject.toml +2 -2
- {django_cfg-1.4.9.dist-info → django_cfg-1.4.10.dist-info}/METADATA +2 -2
- {django_cfg-1.4.9.dist-info → django_cfg-1.4.10.dist-info}/RECORD +22 -22
- {django_cfg-1.4.9.dist-info → django_cfg-1.4.10.dist-info}/WHEEL +0 -0
- {django_cfg-1.4.9.dist-info → django_cfg-1.4.10.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.4.9.dist-info → django_cfg-1.4.10.dist-info}/licenses/LICENSE +0 -0
@@ -96,12 +96,16 @@ class APIAccessMiddleware(MiddlewareMixin):
|
|
96
96
|
def process_request(self, request: HttpRequest) -> Optional[JsonResponse]:
|
97
97
|
"""
|
98
98
|
Process incoming request for API access control.
|
99
|
-
|
99
|
+
|
100
100
|
Returns JsonResponse if access should be denied, None to continue.
|
101
101
|
"""
|
102
102
|
if not self.enabled:
|
103
103
|
return None
|
104
|
-
|
104
|
+
|
105
|
+
# Check if this is a django-cfg internal endpoint check (bypass API key validation)
|
106
|
+
if request.META.get('HTTP_X_DJANGO_CFG_INTERNAL_CHECK') == 'true':
|
107
|
+
return None
|
108
|
+
|
105
109
|
# Check if this path is protected (whitelist approach)
|
106
110
|
if not self._is_protected_path(request.path):
|
107
111
|
return None
|
@@ -56,6 +56,7 @@ class RateLimitingMiddleware(MiddlewareMixin):
|
|
56
56
|
'/admin/',
|
57
57
|
'/static/',
|
58
58
|
'/media/',
|
59
|
+
'/schema/', # Exempt schema generation endpoints (Spectacular)
|
59
60
|
]
|
60
61
|
|
61
62
|
except Exception as e:
|
@@ -74,7 +75,7 @@ class RateLimitingMiddleware(MiddlewareMixin):
|
|
74
75
|
self.burst_allowance = 0.5
|
75
76
|
self.window_size = 60
|
76
77
|
self.window_precision = 10
|
77
|
-
self.exempt_paths = ['/api/health/', '/cfg/', '/admin/']
|
78
|
+
self.exempt_paths = ['/api/health/', '/cfg/', '/admin/', '/schema/']
|
78
79
|
self.cache_timeout = 300
|
79
80
|
|
80
81
|
logger.info(f"Rate Limiting Middleware initialized", extra={
|
@@ -70,7 +70,11 @@ class UsageTrackingMiddleware(MiddlewareMixin):
|
|
70
70
|
"""
|
71
71
|
if not self.enabled:
|
72
72
|
return None
|
73
|
-
|
73
|
+
|
74
|
+
# Check if this is a django-cfg internal endpoint check (skip tracking)
|
75
|
+
if request.META.get('HTTP_X_DJANGO_CFG_INTERNAL_CHECK') == 'true':
|
76
|
+
return None
|
77
|
+
|
74
78
|
# Check if we should track this request
|
75
79
|
if not self._should_track_request(request):
|
76
80
|
return None
|
@@ -319,7 +319,6 @@ class APIKeyManager(models.Manager):
|
|
319
319
|
# Usage statistics
|
320
320
|
usage_stats = queryset.aggregate(
|
321
321
|
total_requests=models.Sum('total_requests'),
|
322
|
-
avg_requests=models.Avg('total_requests'),
|
323
322
|
max_requests=models.Max('total_requests')
|
324
323
|
)
|
325
324
|
stats.update(usage_stats)
|
@@ -196,7 +196,6 @@ class SubscriptionQuerySet(models.QuerySet):
|
|
196
196
|
"""Get usage statistics."""
|
197
197
|
return self.aggregate(
|
198
198
|
total_requests=models.Sum('total_requests'),
|
199
|
-
avg_requests=models.Avg('total_requests'),
|
200
199
|
max_requests=models.Max('total_requests'),
|
201
200
|
active_users=models.Count('user', distinct=True)
|
202
201
|
)
|
@@ -340,16 +340,16 @@ class BalanceService(BaseService):
|
|
340
340
|
created_at__gte=since
|
341
341
|
).aggregate(
|
342
342
|
total_transactions=models.Count('id'),
|
343
|
-
total_volume=models.Sum('
|
343
|
+
total_volume=models.Sum('amount_usd'),
|
344
344
|
deposits=models.Sum(
|
345
|
-
'
|
345
|
+
'amount_usd',
|
346
346
|
filter=models.Q(transaction_type='deposit')
|
347
347
|
),
|
348
348
|
withdrawals=models.Sum(
|
349
|
-
'
|
349
|
+
'amount_usd',
|
350
350
|
filter=models.Q(transaction_type='withdrawal')
|
351
351
|
),
|
352
|
-
avg_transaction=models.Avg('
|
352
|
+
avg_transaction=models.Avg('amount_usd')
|
353
353
|
)
|
354
354
|
|
355
355
|
# Transaction type breakdown
|
@@ -357,7 +357,7 @@ class BalanceService(BaseService):
|
|
357
357
|
created_at__gte=since
|
358
358
|
).values('transaction_type').annotate(
|
359
359
|
count=models.Count('id'),
|
360
|
-
volume=models.Sum('
|
360
|
+
volume=models.Sum('amount_usd')
|
361
361
|
).order_by('-count')
|
362
362
|
|
363
363
|
stats = {
|
@@ -473,8 +473,7 @@ class SubscriptionService(BaseService):
|
|
473
473
|
created_at__gte=since
|
474
474
|
).aggregate(
|
475
475
|
new_subscriptions=models.Count('id'),
|
476
|
-
total_requests=models.Sum('total_requests')
|
477
|
-
avg_requests=models.Avg('total_requests')
|
476
|
+
total_requests=models.Sum('total_requests')
|
478
477
|
)
|
479
478
|
|
480
479
|
stats = {
|
@@ -10,6 +10,7 @@ from rest_framework.response import Response
|
|
10
10
|
from django_filters.rest_framework import DjangoFilterBackend
|
11
11
|
from django.contrib.auth import get_user_model
|
12
12
|
from django.db import models
|
13
|
+
from django.utils import timezone
|
13
14
|
|
14
15
|
from .base import PaymentBaseViewSet, NestedPaymentViewSet, ReadOnlyPaymentViewSet
|
15
16
|
from ...models import UserBalance, Transaction
|
@@ -245,12 +246,12 @@ class TransactionViewSet(ReadOnlyPaymentViewSet):
|
|
245
246
|
'total_transactions': type_transactions.count(),
|
246
247
|
'total_amount': float(
|
247
248
|
type_transactions.aggregate(
|
248
|
-
total=models.Sum('
|
249
|
+
total=models.Sum('amount_usd')
|
249
250
|
)['total'] or 0
|
250
251
|
),
|
251
252
|
'average_amount': float(
|
252
253
|
type_transactions.aggregate(
|
253
|
-
avg=models.Avg('
|
254
|
+
avg=models.Avg('amount_usd')
|
254
255
|
)['avg'] or 0
|
255
256
|
),
|
256
257
|
}
|
@@ -344,14 +345,14 @@ class UserTransactionViewSet(NestedPaymentViewSet):
|
|
344
345
|
summary = queryset.aggregate(
|
345
346
|
total_transactions=models.Count('id'),
|
346
347
|
total_credits=models.Sum(
|
347
|
-
'
|
348
|
-
filter=models.Q(
|
348
|
+
'amount_usd',
|
349
|
+
filter=models.Q(amount_usd__gt=0)
|
349
350
|
),
|
350
351
|
total_debits=models.Sum(
|
351
|
-
'
|
352
|
-
filter=models.Q(
|
352
|
+
'amount_usd',
|
353
|
+
filter=models.Q(amount_usd__lt=0)
|
353
354
|
),
|
354
|
-
net_amount=models.Sum('
|
355
|
+
net_amount=models.Sum('amount_usd'),
|
355
356
|
)
|
356
357
|
|
357
358
|
# Get type breakdown
|
@@ -82,10 +82,10 @@ class PaymentBaseViewSet(viewsets.ModelViewSet):
|
|
82
82
|
return context
|
83
83
|
|
84
84
|
@action(detail=False, methods=['get'])
|
85
|
-
def stats(self, request):
|
85
|
+
def stats(self, request, **kwargs):
|
86
86
|
"""
|
87
87
|
Get statistics for the current queryset.
|
88
|
-
|
88
|
+
|
89
89
|
Returns counts, aggregates, and breakdowns.
|
90
90
|
"""
|
91
91
|
try:
|
@@ -120,10 +120,10 @@ class PaymentBaseViewSet(viewsets.ModelViewSet):
|
|
120
120
|
)
|
121
121
|
|
122
122
|
@action(detail=False, methods=['get'])
|
123
|
-
def health(self, request):
|
123
|
+
def health(self, request, **kwargs):
|
124
124
|
"""
|
125
125
|
Health check for the ViewSet and related services.
|
126
|
-
|
126
|
+
|
127
127
|
Returns service status and basic metrics.
|
128
128
|
"""
|
129
129
|
try:
|
@@ -264,12 +264,16 @@ class NestedPaymentViewSet(PaymentBaseViewSet):
|
|
264
264
|
def get_queryset(self):
|
265
265
|
"""Filter queryset by parent object from URL."""
|
266
266
|
queryset = super().get_queryset()
|
267
|
-
|
267
|
+
|
268
268
|
parent_id = self.kwargs.get(self.parent_lookup_field)
|
269
269
|
if parent_id:
|
270
|
+
# Skip filtering for schema generation placeholders
|
271
|
+
if str(parent_id).lower() in ['test', 'string', 'example']:
|
272
|
+
return queryset.none()
|
273
|
+
|
270
274
|
filter_kwargs = {self.parent_model_field + '_id': parent_id}
|
271
275
|
queryset = queryset.filter(**filter_kwargs)
|
272
|
-
|
276
|
+
|
273
277
|
return queryset
|
274
278
|
|
275
279
|
def perform_create(self, serializer):
|
@@ -204,7 +204,7 @@ class NetworkViewSet(ReadOnlyPaymentViewSet):
|
|
204
204
|
|
205
205
|
def get_queryset(self):
|
206
206
|
"""Optimize queryset with related objects."""
|
207
|
-
return super().get_queryset().select_related('
|
207
|
+
return super().get_queryset().select_related('native_currency')
|
208
208
|
|
209
209
|
@action(detail=False, methods=['get'])
|
210
210
|
def by_currency(self, request):
|
@@ -218,11 +218,11 @@ class NetworkViewSet(ReadOnlyPaymentViewSet):
|
|
218
218
|
|
219
219
|
networks_by_currency = {}
|
220
220
|
for network in queryset:
|
221
|
-
currency_code = network.
|
222
|
-
|
221
|
+
currency_code = network.native_currency.code
|
222
|
+
|
223
223
|
if currency_code not in networks_by_currency:
|
224
224
|
networks_by_currency[currency_code] = {
|
225
|
-
'currency': CurrencyListSerializer(network.
|
225
|
+
'currency': CurrencyListSerializer(network.native_currency).data,
|
226
226
|
'networks': []
|
227
227
|
}
|
228
228
|
|
@@ -10,6 +10,8 @@ from rest_framework.response import Response
|
|
10
10
|
from django_filters.rest_framework import DjangoFilterBackend
|
11
11
|
from django.contrib.auth import get_user_model
|
12
12
|
from django.shortcuts import get_object_or_404
|
13
|
+
from django.utils import timezone
|
14
|
+
from django.db import models
|
13
15
|
|
14
16
|
from .base import PaymentBaseViewSet, NestedPaymentViewSet
|
15
17
|
from ...models import UniversalPayment
|
@@ -371,7 +373,7 @@ class PaymentStatusView(generics.RetrieveAPIView):
|
|
371
373
|
queryset = UniversalPayment.objects.all()
|
372
374
|
serializer_class = PaymentSerializer
|
373
375
|
permission_classes = [permissions.IsAuthenticated]
|
374
|
-
lookup_field = '
|
376
|
+
lookup_field = 'pk' # URL uses <uuid:pk>
|
375
377
|
|
376
378
|
def get_object(self):
|
377
379
|
"""Get payment with permission check."""
|
@@ -344,7 +344,6 @@ class UserSubscriptionViewSet(NestedPaymentViewSet):
|
|
344
344
|
filter=models.Q(expires_at__lt=timezone.now())
|
345
345
|
),
|
346
346
|
total_requests=models.Sum('total_requests'),
|
347
|
-
requests_used=models.Sum('requests_used'),
|
348
347
|
)
|
349
348
|
|
350
349
|
return Response({
|
@@ -352,8 +351,6 @@ class UserSubscriptionViewSet(NestedPaymentViewSet):
|
|
352
351
|
'summary': {
|
353
352
|
**summary,
|
354
353
|
'total_requests': summary['total_requests'] or 0,
|
355
|
-
'requests_used': summary['requests_used'] or 0,
|
356
|
-
'requests_remaining': (summary['total_requests'] or 0) - (summary['requests_used'] or 0),
|
357
354
|
},
|
358
355
|
'generated_at': timezone.now().isoformat()
|
359
356
|
})
|
@@ -430,7 +427,7 @@ class TariffViewSet(ReadOnlyPaymentViewSet):
|
|
430
427
|
|
431
428
|
GET /api/tariffs/free/
|
432
429
|
"""
|
433
|
-
free_tariffs = self.get_queryset().filter(
|
430
|
+
free_tariffs = self.get_queryset().filter(monthly_price_usd=0)
|
434
431
|
serializer = self.get_serializer(free_tariffs, many=True)
|
435
432
|
|
436
433
|
return Response({
|
@@ -447,7 +444,7 @@ class TariffViewSet(ReadOnlyPaymentViewSet):
|
|
447
444
|
|
448
445
|
GET /api/tariffs/paid/
|
449
446
|
"""
|
450
|
-
paid_tariffs = self.get_queryset().filter(
|
447
|
+
paid_tariffs = self.get_queryset().filter(monthly_price_usd__gt=0)
|
451
448
|
serializer = self.get_serializer(paid_tariffs, many=True)
|
452
449
|
|
453
450
|
return Response({
|
@@ -123,14 +123,24 @@ class APIFrameworksGenerator:
|
|
123
123
|
"description": getattr(self.config.revolution, "drf_description", "RESTful API"),
|
124
124
|
"version": getattr(self.config.revolution, "drf_version", "1.0.0"),
|
125
125
|
"schema_path_prefix": f"/{self.config.revolution.api_prefix}/",
|
126
|
-
"enable_browsable_api": getattr(self.config.revolution, "drf_enable_browsable_api",
|
126
|
+
"enable_browsable_api": getattr(self.config.revolution, "drf_enable_browsable_api", True),
|
127
127
|
"enable_throttling": getattr(self.config.revolution, "drf_enable_throttling", False),
|
128
|
+
|
129
|
+
# Django-CFG specific settings
|
130
|
+
"REST_FRAMEWORK_DEFAULT_PAGINATION_CLASS": "django_cfg.middleware.pagination.DefaultPagination",
|
131
|
+
"REST_FRAMEWORK_PAGE_SIZE": 100,
|
132
|
+
"REST_FRAMEWORK_DEFAULT_RENDERER_CLASSES": [
|
133
|
+
"rest_framework.renderers.JSONRenderer",
|
134
|
+
"django_cfg.modules.django_drf_theme.renderers.TailwindBrowsableAPIRenderer",
|
135
|
+
],
|
128
136
|
}
|
129
137
|
|
130
138
|
# Create DRF + Spectacular config with Revolution's comprehensive settings
|
131
139
|
drf_settings = create_drf_spectacular_config(**drf_kwargs)
|
132
140
|
|
133
141
|
logger.info("🚀 Generated DRF + Spectacular settings using Revolution's create_drf_spectacular_config")
|
142
|
+
logger.info(" - Pagination: django_cfg.middleware.pagination.DefaultPagination")
|
143
|
+
logger.info(" - Renderer: TailwindBrowsableAPIRenderer")
|
134
144
|
|
135
145
|
return drf_settings
|
136
146
|
|
@@ -205,9 +215,17 @@ class APIFrameworksGenerator:
|
|
205
215
|
"""
|
206
216
|
Apply DRF settings extensions.
|
207
217
|
|
218
|
+
Note: This method should NOT overwrite existing REST_FRAMEWORK settings.
|
219
|
+
It should only add missing settings or extend existing ones.
|
220
|
+
|
208
221
|
Returns:
|
209
222
|
Dictionary with DRF settings
|
210
223
|
"""
|
224
|
+
# Don't override if Revolution already created full DRF config
|
225
|
+
if self.config.revolution:
|
226
|
+
logger.info("🔧 DRF settings already configured by Revolution, skipping django-cfg extensions")
|
227
|
+
return {}
|
228
|
+
|
211
229
|
settings = {}
|
212
230
|
|
213
231
|
if self.config.drf:
|
@@ -49,7 +49,8 @@ class Command(BaseCommand):
|
|
49
49
|
# Show basic info
|
50
50
|
self.show_environment_info()
|
51
51
|
self.show_email_config()
|
52
|
-
|
52
|
+
self.show_drf_config()
|
53
|
+
|
53
54
|
if options['verbose']:
|
54
55
|
self.show_database_config()
|
55
56
|
self.show_app_config()
|
@@ -122,6 +123,88 @@ class Command(BaseCommand):
|
|
122
123
|
except Exception as e:
|
123
124
|
self.stdout.write(self.style.ERROR(f" ❌ Django CFG Email Service error: {e}"))
|
124
125
|
|
126
|
+
def show_drf_config(self):
|
127
|
+
"""Show DRF and Spectacular configuration."""
|
128
|
+
self.stdout.write(self.style.SUCCESS("\n🔌 DRF & Spectacular Configuration:"))
|
129
|
+
|
130
|
+
# Check REST_FRAMEWORK settings
|
131
|
+
rest_framework = getattr(settings, 'REST_FRAMEWORK', {})
|
132
|
+
if rest_framework:
|
133
|
+
self.stdout.write(" ✅ REST_FRAMEWORK configured")
|
134
|
+
|
135
|
+
# Show key DRF settings
|
136
|
+
drf_settings = {
|
137
|
+
'DEFAULT_SCHEMA_CLASS': rest_framework.get('DEFAULT_SCHEMA_CLASS', 'Not set'),
|
138
|
+
'DEFAULT_AUTHENTICATION_CLASSES': rest_framework.get('DEFAULT_AUTHENTICATION_CLASSES', []),
|
139
|
+
'DEFAULT_PERMISSION_CLASSES': rest_framework.get('DEFAULT_PERMISSION_CLASSES', []),
|
140
|
+
'DEFAULT_PAGINATION_CLASS': rest_framework.get('DEFAULT_PAGINATION_CLASS', 'Not set'),
|
141
|
+
'PAGE_SIZE': rest_framework.get('PAGE_SIZE', 'Not set'),
|
142
|
+
}
|
143
|
+
|
144
|
+
for key, value in drf_settings.items():
|
145
|
+
icon = "✅" if value and value != 'Not set' else "❌"
|
146
|
+
if isinstance(value, list):
|
147
|
+
if value:
|
148
|
+
self.stdout.write(f" {icon} {key}:")
|
149
|
+
for item in value:
|
150
|
+
self.stdout.write(f" - {item}")
|
151
|
+
else:
|
152
|
+
self.stdout.write(f" {icon} {key}: []")
|
153
|
+
else:
|
154
|
+
self.stdout.write(f" {icon} {key}: {value}")
|
155
|
+
else:
|
156
|
+
self.stdout.write(" ❌ REST_FRAMEWORK not configured")
|
157
|
+
|
158
|
+
# Check SPECTACULAR_SETTINGS
|
159
|
+
spectacular = getattr(settings, 'SPECTACULAR_SETTINGS', {})
|
160
|
+
if spectacular:
|
161
|
+
self.stdout.write("\n ✅ SPECTACULAR_SETTINGS configured")
|
162
|
+
|
163
|
+
# Show key Spectacular settings
|
164
|
+
spectacular_settings = {
|
165
|
+
'TITLE': spectacular.get('TITLE', 'Not set'),
|
166
|
+
'VERSION': spectacular.get('VERSION', 'Not set'),
|
167
|
+
'SCHEMA_PATH_PREFIX': spectacular.get('SCHEMA_PATH_PREFIX', 'Not set'),
|
168
|
+
'SERVE_INCLUDE_SCHEMA': spectacular.get('SERVE_INCLUDE_SCHEMA', 'Not set'),
|
169
|
+
}
|
170
|
+
|
171
|
+
for key, value in spectacular_settings.items():
|
172
|
+
icon = "✅" if value != 'Not set' else "❌"
|
173
|
+
self.stdout.write(f" {icon} {key}: {value}")
|
174
|
+
else:
|
175
|
+
self.stdout.write("\n ❌ SPECTACULAR_SETTINGS not configured")
|
176
|
+
|
177
|
+
# Check SimpleJWT settings
|
178
|
+
simple_jwt = getattr(settings, 'SIMPLE_JWT', {})
|
179
|
+
if simple_jwt:
|
180
|
+
self.stdout.write("\n ✅ SIMPLE_JWT configured")
|
181
|
+
|
182
|
+
jwt_settings = {
|
183
|
+
'ACCESS_TOKEN_LIFETIME': simple_jwt.get('ACCESS_TOKEN_LIFETIME', 'Not set'),
|
184
|
+
'REFRESH_TOKEN_LIFETIME': simple_jwt.get('REFRESH_TOKEN_LIFETIME', 'Not set'),
|
185
|
+
'ALGORITHM': simple_jwt.get('ALGORITHM', 'Not set'),
|
186
|
+
}
|
187
|
+
|
188
|
+
for key, value in jwt_settings.items():
|
189
|
+
icon = "✅" if value != 'Not set' else "❌"
|
190
|
+
self.stdout.write(f" {icon} {key}: {value}")
|
191
|
+
else:
|
192
|
+
self.stdout.write("\n ❌ SIMPLE_JWT not configured")
|
193
|
+
|
194
|
+
# Get django-cfg config
|
195
|
+
try:
|
196
|
+
from django_cfg.core.state import get_current_config
|
197
|
+
config = get_current_config()
|
198
|
+
|
199
|
+
if config:
|
200
|
+
self.stdout.write("\n 📋 Django-CFG Config:")
|
201
|
+
self.stdout.write(f" drf: {'✅ Configured' if config.drf else '❌ Not set'}")
|
202
|
+
self.stdout.write(f" spectacular: {'✅ Configured' if config.spectacular else '❌ Not set'}")
|
203
|
+
self.stdout.write(f" jwt: {'✅ Configured' if config.jwt else '❌ Not set'}")
|
204
|
+
self.stdout.write(f" revolution: {'✅ Configured' if config.revolution else '❌ Not set'}")
|
205
|
+
except Exception as e:
|
206
|
+
self.stdout.write(self.style.ERROR(f" ❌ Error getting django-cfg config: {e}"))
|
207
|
+
|
125
208
|
def show_database_config(self):
|
126
209
|
"""Show database configuration."""
|
127
210
|
self.stdout.write(self.style.SUCCESS("\n🗄️ Database Configuration:"))
|
@@ -117,6 +117,7 @@ class ExtendedRevolutionConfig(BaseDjangoRevolutionConfig):
|
|
117
117
|
description="Support tickets and messages API",
|
118
118
|
public=False,
|
119
119
|
auth_required=True,
|
120
|
+
group="cfg",
|
120
121
|
# version="v1",
|
121
122
|
)
|
122
123
|
|
@@ -129,6 +130,7 @@ class ExtendedRevolutionConfig(BaseDjangoRevolutionConfig):
|
|
129
130
|
description="User management, OTP, profiles, and activity tracking API",
|
130
131
|
public=False,
|
131
132
|
auth_required=True,
|
133
|
+
group="cfg",
|
132
134
|
# version="v1",
|
133
135
|
)
|
134
136
|
|
@@ -141,6 +143,7 @@ class ExtendedRevolutionConfig(BaseDjangoRevolutionConfig):
|
|
141
143
|
description="Email campaigns, subscriptions, and newsletter management API",
|
142
144
|
public=False,
|
143
145
|
auth_required=True,
|
146
|
+
group="cfg",
|
144
147
|
# version="v1",
|
145
148
|
)
|
146
149
|
|
@@ -153,6 +156,7 @@ class ExtendedRevolutionConfig(BaseDjangoRevolutionConfig):
|
|
153
156
|
description="Lead collection, contact forms, and CRM integration API",
|
154
157
|
public=True, # Leads can be public for contact forms
|
155
158
|
auth_required=False,
|
159
|
+
group="cfg",
|
156
160
|
# version="v1",
|
157
161
|
)
|
158
162
|
|
@@ -165,6 +169,7 @@ class ExtendedRevolutionConfig(BaseDjangoRevolutionConfig):
|
|
165
169
|
description="Knowledge base, AI chat, embeddings, and search API",
|
166
170
|
public=False,
|
167
171
|
auth_required=True,
|
172
|
+
group="cfg",
|
168
173
|
# version="v1",
|
169
174
|
)
|
170
175
|
|
@@ -177,6 +182,7 @@ class ExtendedRevolutionConfig(BaseDjangoRevolutionConfig):
|
|
177
182
|
description="Agent definitions, executions, workflows, and tools API",
|
178
183
|
public=False,
|
179
184
|
auth_required=True,
|
185
|
+
group="cfg",
|
180
186
|
# version="v1",
|
181
187
|
)
|
182
188
|
|
@@ -189,6 +195,7 @@ class ExtendedRevolutionConfig(BaseDjangoRevolutionConfig):
|
|
189
195
|
description="Tasks, workflows, and automation API",
|
190
196
|
public=False,
|
191
197
|
auth_required=True,
|
198
|
+
group="cfg",
|
192
199
|
# version="v1",
|
193
200
|
)
|
194
201
|
|
@@ -201,6 +208,7 @@ class ExtendedRevolutionConfig(BaseDjangoRevolutionConfig):
|
|
201
208
|
description="Payments, subscriptions, and billing API",
|
202
209
|
public=False,
|
203
210
|
auth_required=True,
|
211
|
+
group="cfg",
|
204
212
|
# version="v1",
|
205
213
|
)
|
206
214
|
|
@@ -60,7 +60,7 @@ class DashboardManager(BaseCfgModule):
|
|
60
60
|
items=[
|
61
61
|
NavigationItem(title="Overview", icon=Icons.DASHBOARD, link="/admin/"),
|
62
62
|
NavigationItem(title="Settings", icon=Icons.SETTINGS, link="/admin/constance/config/"),
|
63
|
-
NavigationItem(title="Health Check", icon=Icons.HEALTH_AND_SAFETY, link="/cfg/health/"),
|
63
|
+
NavigationItem(title="Health Check", icon=Icons.HEALTH_AND_SAFETY, link="/cfg/health/drf/"),
|
64
64
|
NavigationItem(title="Endpoints Status", icon=Icons.API, link="/cfg/endpoints/drf/"),
|
65
65
|
]
|
66
66
|
),
|
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.10"
|
8
8
|
description = "Django AI framework with built-in agents, type-safe Pydantic v2 configuration, and 8 enterprise apps. Replace settings.py, validate at startup, 90% less code. Production-ready AI workflows for Django."
|
9
9
|
readme = "README.md"
|
10
10
|
keywords = [ "django", "configuration", "pydantic", "settings", "type-safety", "pydantic-settings", "django-environ", "startup-validation", "ide-autocomplete", "ai-agents", "enterprise-django", "django-settings", "type-safe-config",]
|
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,<4.0"
|
13
|
-
dependencies = [ "pydantic>=2.11.0,<3.0", "pydantic[email]>=2.11.0,<3.0", "PyYAML>=6.0,<7.0", "pydantic-yaml>=1.6.0,<2.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", "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", "dramatiq[redis]>=1.18.0,<2.0", "django-dramatiq>=0.14.0,<1.0", "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", "pydantic-ai>=1.0.10,<2.0", "django-revolution>=1.0.
|
13
|
+
dependencies = [ "pydantic>=2.11.0,<3.0", "pydantic[email]>=2.11.0,<3.0", "PyYAML>=6.0,<7.0", "pydantic-yaml>=1.6.0,<2.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", "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", "dramatiq[redis]>=1.18.0,<2.0", "django-dramatiq>=0.14.0,<1.0", "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", "pydantic-ai>=1.0.10,<2.0", "django-revolution>=1.0.46", "tenacity>=9.1.2,<10.0.0", "mypy (>=1.18.2,<2.0.0)", "django-tailwind[reload] (>=4.2.0,<5.0.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.10
|
4
4
|
Summary: Django AI framework with built-in agents, type-safe Pydantic v2 configuration, and 8 enterprise apps. Replace settings.py, validate at startup, 90% less code. Production-ready AI workflows for Django.
|
5
5
|
Project-URL: Homepage, https://djangocfg.com
|
6
6
|
Project-URL: Documentation, https://djangocfg.com
|
@@ -45,7 +45,7 @@ Requires-Dist: django-import-export<5.0,>=4.3.0
|
|
45
45
|
Requires-Dist: django-json-widget<3.0,>=2.0.0
|
46
46
|
Requires-Dist: django-ratelimit<5.0.0,>=4.1.0
|
47
47
|
Requires-Dist: django-redis<7.0,>=6.0.0
|
48
|
-
Requires-Dist: django-revolution>=1.0.
|
48
|
+
Requires-Dist: django-revolution>=1.0.46
|
49
49
|
Requires-Dist: django-tailwind[reload]<5.0.0,>=4.2.0
|
50
50
|
Requires-Dist: django-unfold<1.0,>=0.64.0
|
51
51
|
Requires-Dist: djangorestframework-simplejwt<6.0,>=5.5.0
|
@@ -357,9 +357,9 @@ django_cfg/apps/payments/management/commands/manage_providers.py,sha256=wtN4wttl
|
|
357
357
|
django_cfg/apps/payments/management/commands/process_pending_payments.py,sha256=hh49miYeK4Zbxlp8BXEzgpuiee4lIepLk5leSNBiKh4,13309
|
358
358
|
django_cfg/apps/payments/management/commands/test_providers.py,sha256=IvvJhTNw6KQm1EeWYTUMew0ZHzgUGWpG07JOhrpJEP0,18476
|
359
359
|
django_cfg/apps/payments/middleware/__init__.py,sha256=eL5TmlCKmpW53Ift5rtwS8ss1wUqp4j2gzjGhcAQUQY,380
|
360
|
-
django_cfg/apps/payments/middleware/api_access.py,sha256=
|
361
|
-
django_cfg/apps/payments/middleware/rate_limiting.py,sha256=
|
362
|
-
django_cfg/apps/payments/middleware/usage_tracking.py,sha256=
|
360
|
+
django_cfg/apps/payments/middleware/api_access.py,sha256=_j9VnyMtIiTSgNOeprSgRN10VOmOyDJdjot63JpWoJg,16889
|
361
|
+
django_cfg/apps/payments/middleware/rate_limiting.py,sha256=49VBgxD5Hed9dD56-oYtQj-KXFD8_mQUgfdrsPWsf0I,15255
|
362
|
+
django_cfg/apps/payments/middleware/usage_tracking.py,sha256=uxY1Sb0p-ycXDV6ACGXvNd12GdLBtAy26mB48z2Svdc,11987
|
363
363
|
django_cfg/apps/payments/migrations/0001_initial.py,sha256=uLkgbaSvdPjoTHZ3pVB7aEgVPq_hAyQRWXFqC9-2oGc,48359
|
364
364
|
django_cfg/apps/payments/migrations/0002_rename_payments_un_user_id_7f6e79_idx_payments_un_user_id_8ce187_idx_and_more.py,sha256=MmxPMKYOzafTeVRj1cOOzVEDszKa_VYyqkUD8z7jZEk,1512
|
365
365
|
django_cfg/apps/payments/migrations/0003_universalpayment_status_changed_at.py,sha256=EEs1EzIfpG-tfgx220KZsF8lnn83iwW4blRATJO2vi8,659
|
@@ -373,11 +373,11 @@ django_cfg/apps/payments/models/payments.py,sha256=8uAMreO1tqLZuinFi6fE3fHCaxP5S
|
|
373
373
|
django_cfg/apps/payments/models/subscriptions.py,sha256=o3C3CIupcz3lyvg_hszvHQaiWR7RJQ-pP1eebIDJfBE,10332
|
374
374
|
django_cfg/apps/payments/models/tariffs.py,sha256=b2iDC7hBdZR8TX8aEskM5nTEa5_f0H6-j6wZdcbHdyk,6471
|
375
375
|
django_cfg/apps/payments/models/managers/__init__.py,sha256=56kdXtRJOLHhtnY4arYi15fEAmWWrWJP0F8kn8okpzU,1090
|
376
|
-
django_cfg/apps/payments/models/managers/api_key_managers.py,sha256=
|
376
|
+
django_cfg/apps/payments/models/managers/api_key_managers.py,sha256=u-KJkzIKuOpT3eTDFwbZkBpZ3d0_NrSDxpG8aZSYpNA,10493
|
377
377
|
django_cfg/apps/payments/models/managers/balance_managers.py,sha256=exsd4jJEeKlsF3Q566zrXb-8my2NmxR3b-3Xkc9JTLg,20299
|
378
378
|
django_cfg/apps/payments/models/managers/currency_managers.py,sha256=y-VwYGpnE8zlaKkgx7PDfHZ9VQACTZyhPTUSN7DsCws,16265
|
379
379
|
django_cfg/apps/payments/models/managers/payment_managers.py,sha256=hqyzSvYGuixSmscsrkThn6na2zBlj1vBeRWx7b4dpJw,22525
|
380
|
-
django_cfg/apps/payments/models/managers/subscription_managers.py,sha256=
|
380
|
+
django_cfg/apps/payments/models/managers/subscription_managers.py,sha256=2xDYk17CpK9KYdThUtqxFIAn1fq4SdxHriRIkfJizTE,21634
|
381
381
|
django_cfg/apps/payments/services/__init__.py,sha256=QUFVfTwliUvQWtaw0JqDss_LDamgNZwaej8fzL6Qzco,6147
|
382
382
|
django_cfg/apps/payments/services/cache/__init__.py,sha256=eUUtnNU1gPyJOAHaUeaDD5WOnPb0aSI7klvTGbgccOE,354
|
383
383
|
django_cfg/apps/payments/services/cache_service/__init__.py,sha256=nPNc6N2OZtnt7Mr104wQPrAS0HrCqqgVK6aY185AQao,4292
|
@@ -387,11 +387,11 @@ django_cfg/apps/payments/services/cache_service/keys.py,sha256=U37Dwkboxn0E_B5Mp
|
|
387
387
|
django_cfg/apps/payments/services/cache_service/rate_limit_cache.py,sha256=MjFn5q23WjupNI2wZ9KpUJZR5TxX1zkYp6Cu1okZIfQ,1785
|
388
388
|
django_cfg/apps/payments/services/cache_service/simple_cache.py,sha256=_3PfGAsKzK0crgAxE2T_eHEDt2PqcbzZYwRinZGFqSE,3406
|
389
389
|
django_cfg/apps/payments/services/core/__init__.py,sha256=CY2M4ID3rqcdpbokQSdO_fxtdCfHjsGgBsTznyGPw3k,526
|
390
|
-
django_cfg/apps/payments/services/core/balance_service.py,sha256=
|
390
|
+
django_cfg/apps/payments/services/core/balance_service.py,sha256=cCtk2Mu48L6nWFzCAff9eaqz-ti3NXTyEX4ARNKz6L4,18656
|
391
391
|
django_cfg/apps/payments/services/core/base.py,sha256=KiecVjsjsMGdFI-aPr0nTQnu2Tih_oJG_nhBTKAWjlg,5442
|
392
392
|
django_cfg/apps/payments/services/core/currency_service.py,sha256=krA89MU7asLSB_1C-3330XPfXx9uOLZphPYqQib_lkw,18508
|
393
393
|
django_cfg/apps/payments/services/core/payment_service.py,sha256=ZJQ-8bmbfA_qhudMEo4-2HOLzUJqtwaYhWLwY3b4Bgo,6469
|
394
|
-
django_cfg/apps/payments/services/core/subscription_service.py,sha256=
|
394
|
+
django_cfg/apps/payments/services/core/subscription_service.py,sha256=LOWex6OzzUte322giH5RrAomcYYWCXq23nPkWK0wNfI,21066
|
395
395
|
django_cfg/apps/payments/services/core/webhook_service.py,sha256=5Ly44QDUQJYm7V5xkOoKaPzobwf5MkLjFI6uamrpTY0,16222
|
396
396
|
django_cfg/apps/payments/services/core/currency/__init__.py,sha256=NZk-PHnlTAEE1IvxxNZxXKQj-gy_uAUswrKvSZ8I0TM,275
|
397
397
|
django_cfg/apps/payments/services/core/currency/currency_converter.py,sha256=yFs8wim52mCYLvJRU6XLiRCOYowkpggoZ-BWDXTJifc,1684
|
@@ -460,11 +460,11 @@ django_cfg/apps/payments/templatetags/__init__.py,sha256=K8PcAAZu-q6LgCbrH29BSxw
|
|
460
460
|
django_cfg/apps/payments/templatetags/payment_tags.py,sha256=ooO9a5E6kWyaGoLmx2fam4dHnzb9_drhFYmgPT9em1g,11910
|
461
461
|
django_cfg/apps/payments/views/api/__init__.py,sha256=gKd8dE4i-ebCxjquFHI6UaW6KKgV0RE3RlH22c8O4pU,2005
|
462
462
|
django_cfg/apps/payments/views/api/api_keys.py,sha256=nzlRdkMjDY3-hChbSnAo3MFDqd5lulOcKgeajdQr7KQ,13854
|
463
|
-
django_cfg/apps/payments/views/api/balances.py,sha256=
|
464
|
-
django_cfg/apps/payments/views/api/base.py,sha256=
|
465
|
-
django_cfg/apps/payments/views/api/currencies.py,sha256=
|
466
|
-
django_cfg/apps/payments/views/api/payments.py,sha256=
|
467
|
-
django_cfg/apps/payments/views/api/subscriptions.py,sha256=
|
463
|
+
django_cfg/apps/payments/views/api/balances.py,sha256=7V5UCFWQRYO0ZwWN4N1tDvayt9mip4tqhlu79Rk1OQ8,13152
|
464
|
+
django_cfg/apps/payments/views/api/base.py,sha256=Q5AtoFq9R8EkVsqew8mZiNCzkLn4EsogNvo4fqTh0Hs,10553
|
465
|
+
django_cfg/apps/payments/views/api/currencies.py,sha256=A5Tuy9vwYQoCPS1p4GswQ2xwUgbxHwuB3uiq7NP-SRY,13871
|
466
|
+
django_cfg/apps/payments/views/api/payments.py,sha256=s94lkQYv3SrcUG4BQJekxb3-03ULO3VKoSehCP94U2s,14710
|
467
|
+
django_cfg/apps/payments/views/api/subscriptions.py,sha256=q-QBRrkOc4GBe0iCb1ZJMUnm8roX15-ra0eBBK1GRzU,16414
|
468
468
|
django_cfg/apps/payments/views/api/webhooks.py,sha256=8jCPDYRtg2Hf-JuaaDNt7sOexKjJbxAswIWt8FRgtEE,17289
|
469
469
|
django_cfg/apps/payments/views/overview/__init__.py,sha256=2SbWIJzExZFsOiBWnaIMURUhXnJDJ8mBcueuKFkBhJw,987
|
470
470
|
django_cfg/apps/payments/views/overview/serializers.py,sha256=uxDlzMIrn7hhS0aNExuR2YHZ5Tl1LgeFBfwZwLEu4lo,9654
|
@@ -571,7 +571,7 @@ django_cfg/core/generation/data_generators/__init__.py,sha256=t8YepmMhMysy95tRYG
|
|
571
571
|
django_cfg/core/generation/data_generators/cache.py,sha256=IEwyVBJ-QJgOm5C13z-974YzV73aZO9MCresGweE7PM,3840
|
572
572
|
django_cfg/core/generation/data_generators/database.py,sha256=ixJOB5e-e3N06F2QNQ1NJV0KLy26RxyvoKaRI1x5FIE,3481
|
573
573
|
django_cfg/core/generation/integration_generators/__init__.py,sha256=oarpk8gVezvMJWVjC2wwV4ILLkB3z9Oa_oAhdT3Iwu0,595
|
574
|
-
django_cfg/core/generation/integration_generators/api.py,sha256=
|
574
|
+
django_cfg/core/generation/integration_generators/api.py,sha256=Xi6mba7dqwkopMfT4BdpEW0RWuewNG_gpNuU83Wmp9E,9233
|
575
575
|
django_cfg/core/generation/integration_generators/sessions.py,sha256=W2KJetdF-lgfo54fouLCM6a_iTWGpXZrj1xI2CrtZ7g,1644
|
576
576
|
django_cfg/core/generation/integration_generators/tailwind.py,sha256=nEcaBu-uNJ_O2Y2lHCAc1pG7m8LthnrFFHPxDJqSh3k,1208
|
577
577
|
django_cfg/core/generation/integration_generators/tasks.py,sha256=Wlh9f1dpn_05k7dZxGEm2TegGK-TuP4zVwbCMg5ocM4,2514
|
@@ -618,7 +618,7 @@ django_cfg/dashboard/sections/system.py,sha256=IP4SJMPOL-gqDancE_g46ZbmlveYDvljp
|
|
618
618
|
django_cfg/management/__init__.py,sha256=NrLAhiS59hqjy-bipOC1abNuRiNm5BpKXmjN05VzKbM,28
|
619
619
|
django_cfg/management/commands/__init__.py,sha256=GqJDbjiwRa9Y9uvf695EZ-Y42vQIMHp5YkjhMoeAM9I,417
|
620
620
|
django_cfg/management/commands/check_endpoints.py,sha256=5I-8cbVD6aA9g6_j_JI76NoZCSwZTy21B7hxNKbR4OI,6275
|
621
|
-
django_cfg/management/commands/check_settings.py,sha256=
|
621
|
+
django_cfg/management/commands/check_settings.py,sha256=lh5G4FmwGRpmQG20OikL6aqf-BgEb0I8wWbNnco-QKw,15771
|
622
622
|
django_cfg/management/commands/clear_constance.py,sha256=tX6YUeJsmxJxXLQRDX3VUkUP9t6B1gAyVrBl4krQ6K0,8263
|
623
623
|
django_cfg/management/commands/create_token.py,sha256=NspV-9j-T0dDjqY6ccJeuVqTB3v4ne1Jc43G2tKuioI,12015
|
624
624
|
django_cfg/management/commands/generate.py,sha256=tvBahlXOu63H7d-7Ree1WuR_6saebUrcbk5DuqDdMpc,4358
|
@@ -661,7 +661,7 @@ django_cfg/models/base/module.py,sha256=P6YowmE-VOqp_L25Ijxj2hjjNhB9xtlm8G35DHWq
|
|
661
661
|
django_cfg/models/django/__init__.py,sha256=i0GblTO8rF1J_WjT55WjhdbWN10l0UeR6mSFqdnOfak,347
|
662
662
|
django_cfg/models/django/constance.py,sha256=IVklMTtusxWnWaU3PSatGLQfg5qY_Y89MZQjsJFwbCk,9175
|
663
663
|
django_cfg/models/django/environment.py,sha256=jdg6DXQrnuLSdfZNV4KoFlkiPl1n2jOicPU8NFzyB5U,9439
|
664
|
-
django_cfg/models/django/revolution.py,sha256=
|
664
|
+
django_cfg/models/django/revolution.py,sha256=NONFa3U-w2HSMKumEh0BOD5HVI3ghiMvDbISpWC_wr4,9005
|
665
665
|
django_cfg/models/infrastructure/__init__.py,sha256=If0XLyDNaR_F6rOhDJBCT5RmkOOoNcY61L70pQvaO1s,369
|
666
666
|
django_cfg/models/infrastructure/cache.py,sha256=N6LWinyokWcmuJmInn0q48TQq0Je-xXMJdZ0DbelGPU,12175
|
667
667
|
django_cfg/models/infrastructure/logging.py,sha256=6nQNQPUKEL7TAYX1KcYgsqHBKnHWoUnqhR54bxcr40s,10637
|
@@ -856,7 +856,7 @@ django_cfg/modules/django_twilio/templates/guide.md,sha256=nZfwx-sgWyK5NApm93zOe
|
|
856
856
|
django_cfg/modules/django_twilio/templates/sendgrid_otp_email.html,sha256=sXR6_D9hmOFfk9CrfPizpLddVhkRirBWpZd_ioEsxVk,6671
|
857
857
|
django_cfg/modules/django_twilio/templates/sendgrid_test_data.json,sha256=fh1VyuSiDELHsS_CIz9gp7tlsMAEjaDOoqbAPSZ3yyo,339
|
858
858
|
django_cfg/modules/django_unfold/__init__.py,sha256=Z91x1iGmkzlRbEb2L9OCFmYDKNAV9C4G3i15j5S0esc,1898
|
859
|
-
django_cfg/modules/django_unfold/dashboard.py,sha256=
|
859
|
+
django_cfg/modules/django_unfold/dashboard.py,sha256=qzbk4LblELnQYE_HLVrf25-XHrksoaZAMbfWC59qLE8,18112
|
860
860
|
django_cfg/modules/django_unfold/models.py,sha256=bY6QSSaH_-r9vOTkSQjxeIkl5RaED7XkxXkT8-W5stk,4014
|
861
861
|
django_cfg/modules/django_unfold/system_monitor.py,sha256=cznZqldRJqiSLSJbs4U7R2rX8ClzoIpqdfXdXqI2iQw,6955
|
862
862
|
django_cfg/modules/django_unfold/tailwind.py,sha256=X9o1K3QL0VwUISgJ26sLb6zkdK-00qiDuekqTw-fydc,10846
|
@@ -950,9 +950,9 @@ django_cfg/utils/version_check.py,sha256=jI4v3YMdQriUEeb_TvRl511sDghy6I75iKRDUaN
|
|
950
950
|
django_cfg/CHANGELOG.md,sha256=jtT3EprqEJkqSUh7IraP73vQ8PmKUMdRtznQsEnqDZk,2052
|
951
951
|
django_cfg/CONTRIBUTING.md,sha256=DU2kyQ6PU0Z24ob7O_OqKWEYHcZmJDgzw-lQCmu6uBg,3041
|
952
952
|
django_cfg/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
|
953
|
-
django_cfg/pyproject.toml,sha256=
|
954
|
-
django_cfg-1.4.
|
955
|
-
django_cfg-1.4.
|
956
|
-
django_cfg-1.4.
|
957
|
-
django_cfg-1.4.
|
958
|
-
django_cfg-1.4.
|
953
|
+
django_cfg/pyproject.toml,sha256=1ESG8akuC9NoeAKzjod1amQLwukZTA589WlVQYcOQV4,8325
|
954
|
+
django_cfg-1.4.10.dist-info/METADATA,sha256=Q6efBHctBNjYMMNf60dYw5ZG5s1TWYkeb7V0xRT_lLU,22538
|
955
|
+
django_cfg-1.4.10.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
956
|
+
django_cfg-1.4.10.dist-info/entry_points.txt,sha256=Ucmde4Z2wEzgb4AggxxZ0zaYDb9HpyE5blM3uJ0_VNg,56
|
957
|
+
django_cfg-1.4.10.dist-info/licenses/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
|
958
|
+
django_cfg-1.4.10.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|