django-cfg 1.4.10__py3-none-any.whl → 1.4.13__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/agents/management/commands/create_agent.py +1 -1
- django_cfg/apps/agents/management/commands/orchestrator_status.py +3 -3
- django_cfg/apps/newsletter/serializers.py +40 -3
- django_cfg/apps/newsletter/views/campaigns.py +12 -3
- django_cfg/apps/newsletter/views/emails.py +14 -3
- django_cfg/apps/newsletter/views/subscriptions.py +12 -2
- django_cfg/apps/payments/views/api/currencies.py +49 -6
- django_cfg/apps/payments/views/api/webhooks.py +72 -7
- django_cfg/apps/payments/views/overview/serializers.py +34 -1
- django_cfg/apps/payments/views/overview/views.py +2 -1
- django_cfg/apps/payments/views/serializers/payments.py +6 -6
- django_cfg/apps/urls.py +106 -45
- django_cfg/core/base/config_model.py +2 -2
- django_cfg/core/constants.py +1 -1
- django_cfg/core/generation/integration_generators/__init__.py +1 -1
- django_cfg/core/generation/integration_generators/api.py +73 -49
- django_cfg/core/integration/display/startup.py +30 -22
- django_cfg/core/integration/url_integration.py +15 -16
- django_cfg/management/commands/check_endpoints.py +11 -160
- django_cfg/management/commands/check_settings.py +13 -348
- django_cfg/management/commands/clear_constance.py +13 -201
- django_cfg/management/commands/create_token.py +13 -321
- django_cfg/management/commands/generate_clients.py +23 -0
- django_cfg/management/commands/list_urls.py +13 -306
- django_cfg/management/commands/migrate_all.py +13 -126
- django_cfg/management/commands/migrator.py +13 -396
- django_cfg/management/commands/rundramatiq.py +15 -247
- django_cfg/management/commands/rundramatiq_simulator.py +12 -429
- django_cfg/management/commands/runserver_ngrok.py +15 -160
- django_cfg/management/commands/script.py +12 -488
- django_cfg/management/commands/show_config.py +12 -215
- django_cfg/management/commands/show_urls.py +12 -342
- django_cfg/management/commands/superuser.py +15 -295
- django_cfg/management/commands/task_clear.py +14 -217
- django_cfg/management/commands/task_status.py +13 -248
- django_cfg/management/commands/test_email.py +15 -86
- django_cfg/management/commands/test_telegram.py +14 -61
- django_cfg/management/commands/test_twilio.py +15 -105
- django_cfg/management/commands/tree.py +13 -383
- django_cfg/management/commands/validate_openapi.py +10 -0
- django_cfg/middleware/README.md +1 -1
- django_cfg/middleware/user_activity.py +3 -3
- django_cfg/models/__init__.py +2 -2
- django_cfg/models/api/drf/spectacular.py +6 -6
- django_cfg/models/django/__init__.py +2 -2
- django_cfg/models/django/openapi.py +162 -0
- django_cfg/modules/django_admin/management/commands/check_endpoints.py +169 -0
- django_cfg/modules/django_admin/management/commands/check_settings.py +355 -0
- django_cfg/modules/django_admin/management/commands/clear_constance.py +208 -0
- django_cfg/modules/django_admin/management/commands/create_token.py +328 -0
- django_cfg/modules/django_admin/management/commands/list_urls.py +313 -0
- django_cfg/modules/django_admin/management/commands/migrate_all.py +133 -0
- django_cfg/modules/django_admin/management/commands/migrator.py +403 -0
- django_cfg/modules/django_admin/management/commands/script.py +496 -0
- django_cfg/modules/django_admin/management/commands/show_config.py +225 -0
- django_cfg/modules/django_admin/management/commands/show_urls.py +361 -0
- django_cfg/modules/django_admin/management/commands/superuser.py +302 -0
- django_cfg/modules/django_admin/management/commands/tree.py +390 -0
- django_cfg/modules/django_client/__init__.py +20 -0
- django_cfg/modules/django_client/apps.py +35 -0
- django_cfg/modules/django_client/core/__init__.py +56 -0
- django_cfg/modules/django_client/core/archive/__init__.py +11 -0
- django_cfg/modules/django_client/core/archive/manager.py +134 -0
- django_cfg/modules/django_client/core/cli/__init__.py +12 -0
- django_cfg/modules/django_client/core/cli/main.py +235 -0
- django_cfg/modules/django_client/core/config/__init__.py +18 -0
- django_cfg/modules/django_client/core/config/config.py +208 -0
- django_cfg/modules/django_client/core/config/group.py +101 -0
- django_cfg/modules/django_client/core/config/service.py +209 -0
- django_cfg/modules/django_client/core/generator/__init__.py +115 -0
- django_cfg/modules/django_client/core/generator/base.py +838 -0
- django_cfg/modules/django_client/core/generator/python/__init__.py +16 -0
- django_cfg/modules/django_client/core/generator/python/async_client_gen.py +174 -0
- django_cfg/modules/django_client/core/generator/python/files_generator.py +180 -0
- django_cfg/modules/django_client/core/generator/python/generator.py +182 -0
- django_cfg/modules/django_client/core/generator/python/models_generator.py +318 -0
- django_cfg/modules/django_client/core/generator/python/operations_generator.py +278 -0
- django_cfg/modules/django_client/core/generator/python/sync_client_gen.py +102 -0
- django_cfg/modules/django_client/core/generator/python/templates/__init__.py.jinja +9 -0
- django_cfg/modules/django_client/core/generator/python/templates/api_wrapper.py.jinja +153 -0
- django_cfg/modules/django_client/core/generator/python/templates/app_init.py.jinja +6 -0
- django_cfg/modules/django_client/core/generator/python/templates/client/app_client.py.jinja +18 -0
- django_cfg/modules/django_client/core/generator/python/templates/client/flat_client.py.jinja +38 -0
- django_cfg/modules/django_client/core/generator/python/templates/client/main_client.py.jinja +68 -0
- django_cfg/modules/django_client/core/generator/python/templates/client/main_client_file.py.jinja +14 -0
- django_cfg/modules/django_client/core/generator/python/templates/client/operation_method.py.jinja +9 -0
- django_cfg/modules/django_client/core/generator/python/templates/client/sub_client.py.jinja +18 -0
- django_cfg/modules/django_client/core/generator/python/templates/client/sync_main_client.py.jinja +50 -0
- django_cfg/modules/django_client/core/generator/python/templates/client/sync_operation_method.py.jinja +9 -0
- django_cfg/modules/django_client/core/generator/python/templates/client/sync_sub_client.py.jinja +18 -0
- django_cfg/modules/django_client/core/generator/python/templates/client_file.py.jinja +13 -0
- django_cfg/modules/django_client/core/generator/python/templates/main_init.py.jinja +52 -0
- django_cfg/modules/django_client/core/generator/python/templates/models/app_models.py.jinja +17 -0
- django_cfg/modules/django_client/core/generator/python/templates/models/enum_class.py.jinja +17 -0
- django_cfg/modules/django_client/core/generator/python/templates/models/enums.py.jinja +8 -0
- django_cfg/modules/django_client/core/generator/python/templates/models/models.py.jinja +17 -0
- django_cfg/modules/django_client/core/generator/python/templates/models/schema_class.py.jinja +21 -0
- django_cfg/modules/django_client/core/generator/python/templates/pyproject.toml.jinja +55 -0
- django_cfg/modules/django_client/core/generator/python/templates/utils/logger.py.jinja +255 -0
- django_cfg/modules/django_client/core/generator/python/templates/utils/retry.py.jinja +271 -0
- django_cfg/modules/django_client/core/generator/python/templates/utils/schema.py.jinja +12 -0
- django_cfg/modules/django_client/core/generator/typescript/__init__.py +14 -0
- django_cfg/modules/django_client/core/generator/typescript/client_generator.py +165 -0
- django_cfg/modules/django_client/core/generator/typescript/fetchers_generator.py +428 -0
- django_cfg/modules/django_client/core/generator/typescript/files_generator.py +207 -0
- django_cfg/modules/django_client/core/generator/typescript/generator.py +432 -0
- django_cfg/modules/django_client/core/generator/typescript/hooks_generator.py +536 -0
- django_cfg/modules/django_client/core/generator/typescript/models_generator.py +245 -0
- django_cfg/modules/django_client/core/generator/typescript/operations_generator.py +298 -0
- django_cfg/modules/django_client/core/generator/typescript/schemas_generator.py +329 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/api_instance.ts.jinja +131 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/app_index.ts.jinja +2 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/client/app_client.ts.jinja +18 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/client/client.ts.jinja +403 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/client/flat_client.ts.jinja +109 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/client/main_client_file.ts.jinja +10 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/client/operation.ts.jinja +61 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/client/sub_client.ts.jinja +15 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/client_file.ts.jinja +9 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/fetchers/fetchers.ts.jinja +45 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/fetchers/index.ts.jinja +30 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/index.ts.jinja +5 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/main_index.ts.jinja +268 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/models/app_models.ts.jinja +8 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/models/enums.ts.jinja +4 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/models/models.ts.jinja +8 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/package.json.jinja +52 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/schemas/index.ts.jinja +21 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/schemas/schema.ts.jinja +24 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/tsconfig.json.jinja +20 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/utils/errors.ts.jinja +116 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/utils/http.ts.jinja +98 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/utils/logger.ts.jinja +259 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/utils/retry.ts.jinja +175 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/utils/schema.ts.jinja +7 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/utils/storage.ts.jinja +158 -0
- django_cfg/modules/django_client/core/groups/__init__.py +13 -0
- django_cfg/modules/django_client/core/groups/detector.py +178 -0
- django_cfg/modules/django_client/core/groups/manager.py +314 -0
- django_cfg/modules/django_client/core/ir/__init__.py +57 -0
- django_cfg/modules/django_client/core/ir/context.py +387 -0
- django_cfg/modules/django_client/core/ir/operation.py +518 -0
- django_cfg/modules/django_client/core/ir/schema.py +353 -0
- django_cfg/modules/django_client/core/parser/__init__.py +74 -0
- django_cfg/modules/django_client/core/parser/base.py +648 -0
- django_cfg/modules/django_client/core/parser/models/__init__.py +74 -0
- django_cfg/modules/django_client/core/parser/models/base.py +212 -0
- django_cfg/modules/django_client/core/parser/models/components.py +160 -0
- django_cfg/modules/django_client/core/parser/models/openapi.py +203 -0
- django_cfg/modules/django_client/core/parser/models/operation.py +207 -0
- django_cfg/modules/django_client/core/parser/models/schema.py +266 -0
- django_cfg/modules/django_client/core/parser/openapi30.py +56 -0
- django_cfg/modules/django_client/core/parser/openapi31.py +64 -0
- django_cfg/modules/django_client/core/validation/__init__.py +22 -0
- django_cfg/modules/django_client/core/validation/checker.py +134 -0
- django_cfg/modules/django_client/core/validation/fixer.py +216 -0
- django_cfg/modules/django_client/core/validation/reporter.py +480 -0
- django_cfg/modules/django_client/core/validation/rules/__init__.py +11 -0
- django_cfg/modules/django_client/core/validation/rules/base.py +96 -0
- django_cfg/modules/django_client/core/validation/rules/type_hints.py +288 -0
- django_cfg/modules/django_client/core/validation/safety.py +266 -0
- django_cfg/modules/django_client/management/__init__.py +3 -0
- django_cfg/modules/django_client/management/commands/__init__.py +3 -0
- django_cfg/modules/django_client/management/commands/generate_client.py +427 -0
- django_cfg/modules/django_client/management/commands/validate_openapi.py +343 -0
- django_cfg/modules/django_client/pytest.ini +30 -0
- django_cfg/modules/django_client/spectacular/__init__.py +10 -0
- django_cfg/modules/django_client/spectacular/async_detection.py +187 -0
- django_cfg/modules/django_client/spectacular/enum_naming.py +192 -0
- django_cfg/modules/django_client/urls.py +72 -0
- django_cfg/{dashboard → modules/django_dashboard}/DEBUG_README.md +2 -2
- django_cfg/{dashboard → modules/django_dashboard}/REFACTORING_SUMMARY.md +1 -1
- django_cfg/modules/django_dashboard/management/__init__.py +0 -0
- django_cfg/modules/django_dashboard/management/commands/__init__.py +0 -0
- django_cfg/{dashboard → modules/django_dashboard}/management/commands/debug_dashboard.py +5 -5
- django_cfg/modules/django_dashboard/sections/documentation.py +391 -0
- django_cfg/modules/django_email/management/__init__.py +0 -0
- django_cfg/modules/django_email/management/commands/__init__.py +0 -0
- django_cfg/modules/django_email/management/commands/test_email.py +93 -0
- django_cfg/modules/django_logging/LOGGING_GUIDE.md +1 -1
- django_cfg/modules/django_logging/django_logger.py +6 -6
- django_cfg/modules/django_ngrok/management/__init__.py +0 -0
- django_cfg/modules/django_ngrok/management/commands/__init__.py +0 -0
- django_cfg/modules/django_ngrok/management/commands/runserver_ngrok.py +167 -0
- django_cfg/modules/django_tasks/management/__init__.py +0 -0
- django_cfg/modules/django_tasks/management/commands/__init__.py +0 -0
- django_cfg/modules/django_tasks/management/commands/rundramatiq.py +254 -0
- django_cfg/modules/django_tasks/management/commands/rundramatiq_simulator.py +437 -0
- django_cfg/modules/django_tasks/management/commands/task_clear.py +226 -0
- django_cfg/modules/django_tasks/management/commands/task_status.py +257 -0
- django_cfg/modules/django_telegram/management/__init__.py +0 -0
- django_cfg/modules/django_telegram/management/commands/__init__.py +0 -0
- django_cfg/modules/django_telegram/management/commands/test_telegram.py +68 -0
- django_cfg/modules/django_twilio/management/__init__.py +0 -0
- django_cfg/modules/django_twilio/management/commands/__init__.py +0 -0
- django_cfg/modules/django_twilio/management/commands/test_twilio.py +112 -0
- django_cfg/modules/django_unfold/callbacks/main.py +21 -10
- django_cfg/modules/django_unfold/callbacks/revolution.py +41 -36
- django_cfg/pyproject.toml +2 -6
- django_cfg/registry/third_party.py +5 -7
- django_cfg/routing/callbacks.py +1 -1
- django_cfg/static/admin/css/prose-unfold.css +666 -0
- django_cfg/templates/admin/index.html +8 -0
- django_cfg/templates/admin/index_new.html +13 -0
- django_cfg/templates/admin/layouts/dashboard_with_tabs.html +15 -3
- django_cfg/templates/admin/sections/documentation_section.html +172 -0
- django_cfg/templates/admin/snippets/tabs/documentation_tab.html +231 -0
- {django_cfg-1.4.10.dist-info → django_cfg-1.4.13.dist-info}/METADATA +2 -2
- {django_cfg-1.4.10.dist-info → django_cfg-1.4.13.dist-info}/RECORD +224 -74
- django_cfg/management/commands/generate.py +0 -107
- /django_cfg/models/django/{revolution.py → revolution_legacy.py} +0 -0
- /django_cfg/{dashboard → modules/django_admin}/management/__init__.py +0 -0
- /django_cfg/{dashboard → modules/django_admin}/management/commands/__init__.py +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/__init__.py +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/components.py +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/debug.py +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/sections/__init__.py +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/sections/base.py +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/sections/commands.py +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/sections/overview.py +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/sections/stats.py +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/sections/system.py +0 -0
- {django_cfg-1.4.10.dist-info → django_cfg-1.4.13.dist-info}/WHEEL +0 -0
- {django_cfg-1.4.10.dist-info → django_cfg-1.4.13.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.4.10.dist-info → django_cfg-1.4.13.dist-info}/licenses/LICENSE +0 -0
@@ -1,208 +1,20 @@
|
|
1
1
|
"""
|
2
|
-
|
3
|
-
Clear Constance configuration cache and database records.
|
4
|
-
"""
|
5
|
-
|
6
|
-
from django.core.management.base import BaseCommand
|
7
|
-
from django.core.cache import cache
|
8
|
-
from django.conf import settings
|
9
|
-
from django_cfg.modules.django_logging import get_logger
|
10
|
-
|
11
|
-
|
12
|
-
|
2
|
+
Django-CFG wrapper for clear_constance command.
|
13
3
|
|
14
|
-
|
15
|
-
|
4
|
+
This is a simple alias for django_admin.management.commands.clear_constance.
|
5
|
+
All logic is in django_admin module.
|
16
6
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
is_destructive = True
|
21
|
-
|
22
|
-
help = 'Clear Constance configuration cache and database records'
|
23
|
-
|
24
|
-
def add_arguments(self, parser):
|
25
|
-
parser.add_argument(
|
26
|
-
'--cache-only',
|
27
|
-
action='store_true',
|
28
|
-
help='Clear only cache, not database records'
|
29
|
-
)
|
30
|
-
parser.add_argument(
|
31
|
-
'--db-only',
|
32
|
-
action='store_true',
|
33
|
-
help='Clear only database records, not cache'
|
34
|
-
)
|
35
|
-
parser.add_argument(
|
36
|
-
'--confirm',
|
37
|
-
action='store_true',
|
38
|
-
help='Skip confirmation prompt'
|
39
|
-
)
|
40
|
-
parser.add_argument(
|
41
|
-
'--dry-run',
|
42
|
-
action='store_true',
|
43
|
-
help='Show what would be cleared without actually clearing'
|
44
|
-
)
|
45
|
-
|
46
|
-
def handle(self, *args, **options):
|
47
|
-
"""Handle the command execution."""
|
48
|
-
self.logger.info("Starting clear_constance command")
|
49
|
-
self.stdout.write(self.style.SUCCESS('🧹 Constance Clear Tool - Django Config Toolkit\n'))
|
50
|
-
|
51
|
-
# Check if constance is installed
|
52
|
-
if 'constance' not in settings.INSTALLED_APPS:
|
53
|
-
self.stdout.write(self.style.ERROR('❌ Constance is not installed or not in INSTALLED_APPS'))
|
54
|
-
return
|
55
|
-
|
56
|
-
# Determine what to clear
|
57
|
-
clear_cache = not options['db_only']
|
58
|
-
clear_db = not options['cache_only']
|
59
|
-
|
60
|
-
if options['dry_run']:
|
61
|
-
self._show_dry_run(clear_cache, clear_db)
|
62
|
-
return
|
63
|
-
|
64
|
-
# Confirm action
|
65
|
-
if not options['confirm']:
|
66
|
-
if not self._confirm_clear(clear_cache, clear_db):
|
67
|
-
self.stdout.write('Operation cancelled')
|
68
|
-
return
|
69
|
-
|
70
|
-
# Perform clearing
|
71
|
-
self._clear_constance(clear_cache, clear_db)
|
7
|
+
Usage:
|
8
|
+
python manage.py clear_constance
|
9
|
+
"""
|
72
10
|
|
73
|
-
|
74
|
-
"""Show what would be cleared in dry run mode."""
|
75
|
-
self.stdout.write(self.style.SUCCESS('=== Dry Run - What would be cleared ==='))
|
76
|
-
|
77
|
-
if clear_cache:
|
78
|
-
self.stdout.write('🗑️ Cache: All Django cache entries')
|
79
|
-
self.stdout.write('🗑️ Cache: Constance-specific cache entries')
|
80
|
-
|
81
|
-
if clear_db:
|
82
|
-
self.stdout.write('🗑️ Database: All Constance configuration records')
|
83
|
-
|
84
|
-
# Try to show current records count
|
85
|
-
try:
|
86
|
-
from django.apps import apps
|
87
|
-
Constance = apps.get_model('constance', 'Constance')
|
88
|
-
count = Constance.objects.count()
|
89
|
-
self.stdout.write(f' Current records: {count}')
|
90
|
-
except Exception as e:
|
91
|
-
self.stdout.write(f' Could not count records: {e}')
|
92
|
-
|
93
|
-
self.stdout.write('\n✅ Dry run completed - nothing was actually cleared')
|
11
|
+
from django_cfg.modules.django_admin.management.commands.clear_constance import Command as ClearConstanceCommand
|
94
12
|
|
95
|
-
def _confirm_clear(self, clear_cache, clear_db) -> bool:
|
96
|
-
"""Confirm the clear operation with user."""
|
97
|
-
actions = []
|
98
|
-
if clear_cache:
|
99
|
-
actions.append('cache')
|
100
|
-
if clear_db:
|
101
|
-
actions.append('database records')
|
102
|
-
|
103
|
-
action_text = ' and '.join(actions)
|
104
|
-
|
105
|
-
self.stdout.write(
|
106
|
-
self.style.WARNING(f'⚠️ This will clear Constance {action_text}')
|
107
|
-
)
|
108
|
-
self.stdout.write('This action cannot be undone!')
|
109
|
-
|
110
|
-
response = input('Are you sure? [y/N]: ').lower().strip()
|
111
|
-
return response in ['y', 'yes']
|
112
13
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
# Clear cache
|
118
|
-
if clear_cache:
|
119
|
-
try:
|
120
|
-
self.stdout.write('🧹 Clearing Django cache...')
|
121
|
-
cache.clear()
|
122
|
-
self.stdout.write(self.style.SUCCESS('✅ Django cache cleared'))
|
123
|
-
cleared_items.append('cache')
|
124
|
-
|
125
|
-
# Also try to clear specific constance cache keys
|
126
|
-
try:
|
127
|
-
from constance import config as constance_config
|
128
|
-
# Force reload of constance configuration
|
129
|
-
if hasattr(constance_config, '_backend'):
|
130
|
-
constance_config._backend = None
|
131
|
-
self.stdout.write(self.style.SUCCESS('✅ Constance cache backend reset'))
|
132
|
-
except Exception as e:
|
133
|
-
self.stdout.write(self.style.WARNING(f'⚠️ Could not reset Constance backend: {e}'))
|
134
|
-
|
135
|
-
except Exception as e:
|
136
|
-
self.stdout.write(self.style.ERROR(f'❌ Failed to clear cache: {e}'))
|
137
|
-
|
138
|
-
# Clear database records
|
139
|
-
if clear_db:
|
140
|
-
try:
|
141
|
-
self.stdout.write('🗑️ Clearing Constance database records...')
|
142
|
-
|
143
|
-
from django.apps import apps
|
144
|
-
Constance = apps.get_model('constance', 'Constance')
|
145
|
-
|
146
|
-
# Count records before deletion
|
147
|
-
count_before = Constance.objects.count()
|
148
|
-
self.stdout.write(f' Found {count_before} Constance records')
|
149
|
-
|
150
|
-
if count_before > 0:
|
151
|
-
# Delete all records
|
152
|
-
deleted_info = Constance.objects.all().delete()
|
153
|
-
deleted_count = deleted_info[0] if deleted_info else 0
|
154
|
-
|
155
|
-
self.stdout.write(self.style.SUCCESS(f'✅ Deleted {deleted_count} Constance records'))
|
156
|
-
cleared_items.append(f'{deleted_count} database records')
|
157
|
-
else:
|
158
|
-
self.stdout.write('ℹ️ No Constance records found to delete')
|
159
|
-
|
160
|
-
except Exception as e:
|
161
|
-
self.stdout.write(self.style.ERROR(f'❌ Failed to clear database records: {e}'))
|
162
|
-
|
163
|
-
# Show summary
|
164
|
-
if cleared_items:
|
165
|
-
self.stdout.write(
|
166
|
-
self.style.SUCCESS(f'\n🎉 Successfully cleared: {", ".join(cleared_items)}')
|
167
|
-
)
|
168
|
-
self.stdout.write('\n💡 Next steps:')
|
169
|
-
self.stdout.write(' 1. Restart your Django server')
|
170
|
-
self.stdout.write(' 2. Visit Django admin to reconfigure settings')
|
171
|
-
self.stdout.write(' 3. Check that boolean fields now work correctly')
|
172
|
-
else:
|
173
|
-
self.stdout.write(self.style.WARNING('⚠️ Nothing was cleared'))
|
14
|
+
class Command(ClearConstanceCommand):
|
15
|
+
"""
|
16
|
+
Alias for clear_constance command.
|
174
17
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
# Check database records
|
180
|
-
try:
|
181
|
-
from django.apps import apps
|
182
|
-
Constance = apps.get_model('constance', 'Constance')
|
183
|
-
db_count = Constance.objects.count()
|
184
|
-
self.stdout.write(f' Database records: {db_count}')
|
185
|
-
|
186
|
-
if db_count > 0:
|
187
|
-
self.stdout.write(' Recent records:')
|
188
|
-
for record in Constance.objects.all()[:5]:
|
189
|
-
self.stdout.write(f' - {record.key}: {record.value}')
|
190
|
-
if db_count > 5:
|
191
|
-
self.stdout.write(f' ... and {db_count - 5} more')
|
192
|
-
except Exception as e:
|
193
|
-
self.stdout.write(f' Database: Error - {e}')
|
194
|
-
|
195
|
-
# Check cache
|
196
|
-
try:
|
197
|
-
from django.core.cache import cache
|
198
|
-
# Try to get a test key to see if cache is working
|
199
|
-
test_key = 'constance_test_key'
|
200
|
-
cache.set(test_key, 'test_value', 1)
|
201
|
-
test_result = cache.get(test_key)
|
202
|
-
|
203
|
-
if test_result:
|
204
|
-
self.stdout.write(' Cache: Working')
|
205
|
-
else:
|
206
|
-
self.stdout.write(' Cache: Not working or empty')
|
207
|
-
except Exception as e:
|
208
|
-
self.stdout.write(f' Cache: Error - {e}')
|
18
|
+
Simply inherits from ClearConstanceCommand without any changes.
|
19
|
+
"""
|
20
|
+
pass
|
@@ -1,328 +1,20 @@
|
|
1
1
|
"""
|
2
|
-
|
3
|
-
Generate API tokens and authentication tokens.
|
4
|
-
"""
|
5
|
-
|
6
|
-
import os
|
7
|
-
import secrets
|
8
|
-
import string
|
9
|
-
from pathlib import Path
|
10
|
-
from django.core.management.base import BaseCommand
|
11
|
-
from django.contrib.auth import get_user_model
|
12
|
-
from django.conf import settings
|
13
|
-
import questionary
|
14
|
-
from datetime import datetime, timedelta
|
15
|
-
from django_cfg.modules.django_logging import get_logger
|
16
|
-
|
17
|
-
User = get_user_model()
|
18
|
-
|
19
|
-
|
20
|
-
logger = get_logger('create_token')
|
21
|
-
|
22
|
-
class Command(BaseCommand):
|
23
|
-
# Web execution metadata
|
24
|
-
web_executable = False
|
25
|
-
requires_input = True
|
26
|
-
is_destructive = False
|
27
|
-
|
28
|
-
help = 'Create API tokens and authentication tokens'
|
29
|
-
|
30
|
-
def add_arguments(self, parser):
|
31
|
-
parser.add_argument(
|
32
|
-
'--user',
|
33
|
-
type=str,
|
34
|
-
help='Username to create token for'
|
35
|
-
)
|
36
|
-
parser.add_argument(
|
37
|
-
'--type',
|
38
|
-
type=str,
|
39
|
-
choices=['api', 'auth', 'secret'],
|
40
|
-
help='Type of token to create'
|
41
|
-
)
|
42
|
-
parser.add_argument(
|
43
|
-
'--length',
|
44
|
-
type=int,
|
45
|
-
default=32,
|
46
|
-
help='Token length (default: 32)'
|
47
|
-
)
|
48
|
-
parser.add_argument(
|
49
|
-
'--expires',
|
50
|
-
type=int,
|
51
|
-
help='Token expiration in days'
|
52
|
-
)
|
53
|
-
|
54
|
-
def handle(self, *args, **options):
|
55
|
-
logger.info("Starting create_token command")
|
56
|
-
if options['user'] and options['type']:
|
57
|
-
self.create_token_for_user(
|
58
|
-
username=options['user'],
|
59
|
-
token_type=options['type'],
|
60
|
-
length=options['length'],
|
61
|
-
expires_days=options['expires']
|
62
|
-
)
|
63
|
-
else:
|
64
|
-
self.show_interactive_menu()
|
2
|
+
Django-CFG wrapper for create_token command.
|
65
3
|
|
66
|
-
|
67
|
-
|
68
|
-
self.stdout.write(self.style.SUCCESS('\n🔑 Token Creation Tool - Django Config Toolkit\n'))
|
4
|
+
This is a simple alias for django_admin.management.commands.create_token.
|
5
|
+
All logic is in django_admin module.
|
69
6
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
questionary.Choice('🔒 Create Secret Key', value='secret'),
|
74
|
-
questionary.Choice('👤 Create Token for User', value='user'),
|
75
|
-
questionary.Choice('📝 Generate Django Secret Key', value='django_secret'),
|
76
|
-
questionary.Choice('❌ Exit', value='exit')
|
77
|
-
]
|
78
|
-
|
79
|
-
choice = questionary.select(
|
80
|
-
'Select token type:',
|
81
|
-
choices=choices
|
82
|
-
).ask()
|
83
|
-
|
84
|
-
if choice == 'api':
|
85
|
-
self.create_api_token()
|
86
|
-
elif choice == 'auth':
|
87
|
-
self.create_auth_token()
|
88
|
-
elif choice == 'secret':
|
89
|
-
self.create_secret_key()
|
90
|
-
elif choice == 'user':
|
91
|
-
self.create_token_for_user_interactive()
|
92
|
-
elif choice == 'django_secret':
|
93
|
-
self.generate_django_secret_key()
|
94
|
-
elif choice == 'exit':
|
95
|
-
self.stdout.write('Goodbye! 👋')
|
96
|
-
return
|
97
|
-
|
98
|
-
def create_api_token(self):
|
99
|
-
"""Create API token"""
|
100
|
-
self.stdout.write(self.style.SUCCESS('🔑 Creating API Token...'))
|
101
|
-
|
102
|
-
# Get token details
|
103
|
-
token_name = questionary.text('Token name:').ask()
|
104
|
-
if not token_name:
|
105
|
-
self.stdout.write(self.style.ERROR('❌ Token name is required'))
|
106
|
-
return
|
107
|
-
|
108
|
-
token_length = questionary.select(
|
109
|
-
'Token length:',
|
110
|
-
choices=['32', '64', '128', '256']
|
111
|
-
).ask()
|
112
|
-
|
113
|
-
expires = questionary.select(
|
114
|
-
'Token expiration:',
|
115
|
-
choices=['Never', '30 days', '90 days', '1 year']
|
116
|
-
).ask()
|
117
|
-
|
118
|
-
# Generate token
|
119
|
-
token = self.generate_token(int(token_length))
|
120
|
-
|
121
|
-
# Calculate expiration
|
122
|
-
expiration_date = None
|
123
|
-
if expires != 'Never':
|
124
|
-
days_map = {
|
125
|
-
'30 days': 30,
|
126
|
-
'90 days': 90,
|
127
|
-
'1 year': 365
|
128
|
-
}
|
129
|
-
expiration_date = datetime.now() + timedelta(days=days_map[expires])
|
130
|
-
|
131
|
-
# Save token (in a real app, you'd save to database)
|
132
|
-
self.save_token_to_file('api_token', token, token_name, expiration_date)
|
133
|
-
|
134
|
-
self.stdout.write(self.style.SUCCESS(f'✅ API Token created: {token}'))
|
135
|
-
self.stdout.write(f'📝 Name: {token_name}')
|
136
|
-
if expiration_date:
|
137
|
-
self.stdout.write(f'⏰ Expires: {expiration_date.strftime("%Y-%m-%d %H:%M:%S")}')
|
138
|
-
|
139
|
-
def create_auth_token(self):
|
140
|
-
"""Create authentication token"""
|
141
|
-
self.stdout.write(self.style.SUCCESS('🔐 Creating Auth Token...'))
|
142
|
-
|
143
|
-
# Get token details
|
144
|
-
token_name = questionary.text('Token name:').ask()
|
145
|
-
if not token_name:
|
146
|
-
self.stdout.write(self.style.ERROR('❌ Token name is required'))
|
147
|
-
return
|
148
|
-
|
149
|
-
token_length = questionary.select(
|
150
|
-
'Token length:',
|
151
|
-
choices=['32', '64', '128']
|
152
|
-
).ask()
|
153
|
-
|
154
|
-
# Generate token
|
155
|
-
token = self.generate_token(int(token_length))
|
156
|
-
|
157
|
-
# Save token
|
158
|
-
self.save_token_to_file('auth_token', token, token_name)
|
159
|
-
|
160
|
-
self.stdout.write(self.style.SUCCESS(f'✅ Auth Token created: {token}'))
|
161
|
-
self.stdout.write(f'📝 Name: {token_name}')
|
162
|
-
|
163
|
-
def create_secret_key(self):
|
164
|
-
"""Create secret key"""
|
165
|
-
self.stdout.write(self.style.SUCCESS('🔒 Creating Secret Key...'))
|
166
|
-
|
167
|
-
# Get key details
|
168
|
-
key_name = questionary.text('Secret key name:').ask()
|
169
|
-
if not key_name:
|
170
|
-
self.stdout.write(self.style.ERROR('❌ Key name is required'))
|
171
|
-
return
|
172
|
-
|
173
|
-
key_length = questionary.select(
|
174
|
-
'Key length:',
|
175
|
-
choices=['32', '64', '128', '256']
|
176
|
-
).ask()
|
177
|
-
|
178
|
-
# Generate secret key
|
179
|
-
secret_key = self.generate_secret_key(int(key_length))
|
180
|
-
|
181
|
-
# Save key
|
182
|
-
self.save_token_to_file('secret_key', secret_key, key_name)
|
183
|
-
|
184
|
-
self.stdout.write(self.style.SUCCESS(f'✅ Secret Key created: {secret_key}'))
|
185
|
-
self.stdout.write(f'📝 Name: {key_name}')
|
186
|
-
|
187
|
-
def create_token_for_user_interactive(self):
|
188
|
-
"""Create token for user interactively"""
|
189
|
-
self.stdout.write(self.style.SUCCESS('👤 Creating Token for User...'))
|
190
|
-
|
191
|
-
# Get user
|
192
|
-
username = questionary.text('Username:').ask()
|
193
|
-
if not username:
|
194
|
-
self.stdout.write(self.style.ERROR('❌ Username is required'))
|
195
|
-
return
|
196
|
-
|
197
|
-
# Check if user exists
|
198
|
-
try:
|
199
|
-
user = User.objects.get(username=username)
|
200
|
-
except User.DoesNotExist:
|
201
|
-
self.stdout.write(self.style.ERROR(f'❌ User {username} does not exist'))
|
202
|
-
return
|
203
|
-
|
204
|
-
# Get token type
|
205
|
-
token_type = questionary.select(
|
206
|
-
'Token type:',
|
207
|
-
choices=['API Token', 'Auth Token', 'Secret Key']
|
208
|
-
).ask()
|
209
|
-
|
210
|
-
# Get token length
|
211
|
-
token_length = questionary.select(
|
212
|
-
'Token length:',
|
213
|
-
choices=['32', '64', '128']
|
214
|
-
).ask()
|
215
|
-
|
216
|
-
# Get expiration
|
217
|
-
expires = questionary.select(
|
218
|
-
'Token expiration:',
|
219
|
-
choices=['Never', '30 days', '90 days', '1 year']
|
220
|
-
).ask()
|
221
|
-
|
222
|
-
# Create token
|
223
|
-
self.create_token_for_user(
|
224
|
-
username=username,
|
225
|
-
token_type=token_type.lower().replace(' ', '_'),
|
226
|
-
length=int(token_length),
|
227
|
-
expires_days=None if expires == 'Never' else {
|
228
|
-
'30 days': 30,
|
229
|
-
'90 days': 90,
|
230
|
-
'1 year': 365
|
231
|
-
}[expires]
|
232
|
-
)
|
233
|
-
|
234
|
-
def create_token_for_user(self, username, token_type, length=32, expires_days=None):
|
235
|
-
"""Create token for specific user"""
|
236
|
-
try:
|
237
|
-
user = User.objects.get(username=username)
|
238
|
-
except User.DoesNotExist:
|
239
|
-
self.stdout.write(self.style.ERROR(f'❌ User {username} does not exist'))
|
240
|
-
return
|
241
|
-
|
242
|
-
# Generate token
|
243
|
-
if token_type == 'secret_key':
|
244
|
-
token = self.generate_secret_key(length)
|
245
|
-
else:
|
246
|
-
token = self.generate_token(length)
|
247
|
-
|
248
|
-
# Calculate expiration
|
249
|
-
expiration_date = None
|
250
|
-
if expires_days:
|
251
|
-
expiration_date = datetime.now() + timedelta(days=expires_days)
|
252
|
-
|
253
|
-
# Save token
|
254
|
-
token_name = f"{username}_{token_type}_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
|
255
|
-
self.save_token_to_file(token_type, token, token_name, expiration_date, user)
|
256
|
-
|
257
|
-
self.stdout.write(self.style.SUCCESS(f'✅ {token_type.title()} created for {username}'))
|
258
|
-
self.stdout.write(f'🔑 Token: {token}')
|
259
|
-
self.stdout.write(f'📝 Name: {token_name}')
|
260
|
-
if expiration_date:
|
261
|
-
self.stdout.write(f'⏰ Expires: {expiration_date.strftime("%Y-%m-%d %H:%M:%S")}')
|
262
|
-
|
263
|
-
def generate_django_secret_key(self):
|
264
|
-
"""Generate Django secret key"""
|
265
|
-
self.stdout.write(self.style.SUCCESS('🔐 Generating Django Secret Key...'))
|
266
|
-
|
267
|
-
# Generate Django-compatible secret key
|
268
|
-
secret_key = self.generate_django_secret()
|
269
|
-
|
270
|
-
# Save to file
|
271
|
-
self.save_token_to_file('django_secret', secret_key, 'django_secret_key')
|
272
|
-
|
273
|
-
self.stdout.write(self.style.SUCCESS(f'✅ Django Secret Key generated: {secret_key}'))
|
274
|
-
self.stdout.write('💡 Add this to your .env file as SECRET_KEY=...')
|
7
|
+
Usage:
|
8
|
+
python manage.py create_token
|
9
|
+
"""
|
275
10
|
|
276
|
-
|
277
|
-
"""Generate random token"""
|
278
|
-
alphabet = string.ascii_letters + string.digits
|
279
|
-
return ''.join(secrets.choice(alphabet) for _ in range(length))
|
11
|
+
from django_cfg.modules.django_admin.management.commands.create_token import Command as CreateTokenCommand
|
280
12
|
|
281
|
-
def generate_secret_key(self, length=64):
|
282
|
-
"""Generate secret key"""
|
283
|
-
alphabet = string.ascii_letters + string.digits + string.punctuation
|
284
|
-
# Remove characters that might cause issues in config files
|
285
|
-
alphabet = alphabet.replace('"', '').replace("'", '').replace('\\', '')
|
286
|
-
return ''.join(secrets.choice(alphabet) for _ in range(length))
|
287
13
|
|
288
|
-
|
289
|
-
|
290
|
-
|
14
|
+
class Command(CreateTokenCommand):
|
15
|
+
"""
|
16
|
+
Alias for create_token command.
|
291
17
|
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
tokens_dir = Path('tokens')
|
296
|
-
tokens_dir.mkdir(exist_ok=True)
|
297
|
-
|
298
|
-
# Create token file
|
299
|
-
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
|
300
|
-
filename = f"{token_type}_{name}_{timestamp}.txt"
|
301
|
-
filepath = tokens_dir / filename
|
302
|
-
|
303
|
-
with open(filepath, 'w') as f:
|
304
|
-
f.write(f"Token Type: {token_type}\n")
|
305
|
-
f.write(f"Name: {name}\n")
|
306
|
-
f.write(f"Token: {token}\n")
|
307
|
-
f.write(f"Created: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
|
308
|
-
if expiration_date:
|
309
|
-
f.write(f"Expires: {expiration_date.strftime('%Y-%m-%d %H:%M:%S')}\n")
|
310
|
-
if user:
|
311
|
-
f.write(f"User: {user.username} ({user.email})\n")
|
312
|
-
f.write(f"\n# Add to your configuration:\n")
|
313
|
-
f.write(f"# {token_type.upper()}_KEY={token}\n")
|
314
|
-
|
315
|
-
self.stdout.write(f'💾 Token saved to: {filepath}')
|
316
|
-
|
317
|
-
# Also save to .env format
|
318
|
-
env_filename = f"{token_type}_{name}_{timestamp}.env"
|
319
|
-
env_filepath = tokens_dir / env_filename
|
320
|
-
|
321
|
-
with open(env_filepath, 'w') as f:
|
322
|
-
f.write(f"# {token_type.title()} - {name}\n")
|
323
|
-
f.write(f"# Created: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
|
324
|
-
if expiration_date:
|
325
|
-
f.write(f"# Expires: {expiration_date.strftime('%Y-%m-%d %H:%M:%S')}\n")
|
326
|
-
f.write(f"{token_type.upper()}_KEY={token}\n")
|
327
|
-
|
328
|
-
self.stdout.write(f'💾 Environment file saved to: {env_filepath}')
|
18
|
+
Simply inherits from CreateTokenCommand without any changes.
|
19
|
+
"""
|
20
|
+
pass
|
@@ -0,0 +1,23 @@
|
|
1
|
+
"""
|
2
|
+
Django-CFG wrapper for generate_client command.
|
3
|
+
|
4
|
+
This is a simple alias for django_client.management.commands.generate_client.
|
5
|
+
All logic is in django_client module.
|
6
|
+
|
7
|
+
Usage:
|
8
|
+
python manage.py generate_clients --groups blog shop
|
9
|
+
python manage.py generate_clients --python
|
10
|
+
python manage.py generate_clients --list-groups
|
11
|
+
"""
|
12
|
+
|
13
|
+
from django_cfg.modules.django_client.management.commands.generate_client import Command as DjangoClientCommand
|
14
|
+
|
15
|
+
|
16
|
+
class Command(DjangoClientCommand):
|
17
|
+
"""
|
18
|
+
Alias for generate_client command.
|
19
|
+
|
20
|
+
Simply inherits from DjangoClientCommand without any changes.
|
21
|
+
This allows both 'generate_client' and 'generate_clients' to work.
|
22
|
+
"""
|
23
|
+
pass
|