django-cfg 1.1.82__py3-none-any.whl → 1.2.0__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 +20 -448
- django_cfg/apps/accounts/README.md +3 -3
- django_cfg/apps/accounts/admin/__init__.py +0 -2
- django_cfg/apps/accounts/admin/activity.py +2 -9
- django_cfg/apps/accounts/admin/filters.py +0 -42
- django_cfg/apps/accounts/admin/inlines.py +8 -8
- django_cfg/apps/accounts/admin/otp.py +5 -5
- django_cfg/apps/accounts/admin/registration_source.py +1 -8
- django_cfg/apps/accounts/admin/user.py +12 -20
- django_cfg/apps/accounts/managers/user_manager.py +2 -129
- django_cfg/apps/accounts/migrations/0006_remove_twilioresponse_otp_secret_and_more.py +46 -0
- django_cfg/apps/accounts/models.py +3 -123
- django_cfg/apps/accounts/serializers/otp.py +40 -44
- django_cfg/apps/accounts/serializers/profile.py +0 -2
- django_cfg/apps/accounts/services/otp_service.py +98 -186
- django_cfg/apps/accounts/signals.py +25 -15
- django_cfg/apps/accounts/utils/auth_email_service.py +84 -0
- django_cfg/apps/accounts/views/otp.py +35 -36
- django_cfg/apps/agents/README.md +129 -0
- django_cfg/apps/agents/__init__.py +68 -0
- django_cfg/apps/agents/admin/__init__.py +17 -0
- django_cfg/apps/agents/admin/execution_admin.py +460 -0
- django_cfg/apps/agents/admin/registry_admin.py +360 -0
- django_cfg/apps/agents/admin/toolsets_admin.py +482 -0
- django_cfg/apps/agents/apps.py +29 -0
- django_cfg/apps/agents/core/__init__.py +20 -0
- django_cfg/apps/agents/core/agent.py +281 -0
- django_cfg/apps/agents/core/dependencies.py +154 -0
- django_cfg/apps/agents/core/exceptions.py +66 -0
- django_cfg/apps/agents/core/models.py +106 -0
- django_cfg/apps/agents/core/orchestrator.py +391 -0
- django_cfg/apps/agents/examples/__init__.py +3 -0
- django_cfg/apps/agents/examples/simple_example.py +161 -0
- django_cfg/apps/agents/integration/__init__.py +14 -0
- django_cfg/apps/agents/integration/middleware.py +80 -0
- django_cfg/apps/agents/integration/registry.py +345 -0
- django_cfg/apps/agents/integration/signals.py +50 -0
- django_cfg/apps/agents/management/__init__.py +3 -0
- django_cfg/apps/agents/management/commands/__init__.py +3 -0
- django_cfg/apps/agents/management/commands/create_agent.py +365 -0
- django_cfg/apps/agents/management/commands/orchestrator_status.py +191 -0
- django_cfg/apps/agents/managers/__init__.py +23 -0
- django_cfg/apps/agents/managers/execution.py +236 -0
- django_cfg/apps/agents/managers/registry.py +254 -0
- django_cfg/apps/agents/managers/toolsets.py +496 -0
- django_cfg/apps/agents/migrations/0001_initial.py +286 -0
- django_cfg/apps/agents/migrations/__init__.py +5 -0
- django_cfg/apps/agents/models/__init__.py +15 -0
- django_cfg/apps/agents/models/execution.py +215 -0
- django_cfg/apps/agents/models/registry.py +220 -0
- django_cfg/apps/agents/models/toolsets.py +305 -0
- django_cfg/apps/agents/patterns/__init__.py +24 -0
- django_cfg/apps/agents/patterns/content_agents.py +234 -0
- django_cfg/apps/agents/toolsets/__init__.py +15 -0
- django_cfg/apps/agents/toolsets/cache_toolset.py +285 -0
- django_cfg/apps/agents/toolsets/django_toolset.py +220 -0
- django_cfg/apps/agents/toolsets/file_toolset.py +324 -0
- django_cfg/apps/agents/toolsets/orm_toolset.py +319 -0
- django_cfg/apps/agents/urls.py +46 -0
- django_cfg/apps/knowbase/README.md +150 -0
- django_cfg/apps/knowbase/__init__.py +27 -0
- django_cfg/apps/knowbase/admin/__init__.py +23 -0
- django_cfg/apps/knowbase/admin/archive_admin.py +857 -0
- django_cfg/apps/knowbase/admin/chat_admin.py +386 -0
- django_cfg/apps/knowbase/admin/document_admin.py +650 -0
- django_cfg/apps/knowbase/admin/external_data_admin.py +685 -0
- django_cfg/apps/knowbase/apps.py +81 -0
- django_cfg/apps/knowbase/config/README.md +176 -0
- django_cfg/apps/knowbase/config/__init__.py +51 -0
- django_cfg/apps/knowbase/config/constance_fields.py +186 -0
- django_cfg/apps/knowbase/config/constance_settings.py +200 -0
- django_cfg/apps/knowbase/config/settings.py +444 -0
- django_cfg/apps/knowbase/examples/__init__.py +3 -0
- django_cfg/apps/knowbase/examples/external_data_usage.py +191 -0
- django_cfg/apps/knowbase/management/__init__.py +0 -0
- django_cfg/apps/knowbase/management/commands/__init__.py +0 -0
- django_cfg/apps/knowbase/management/commands/knowbase_stats.py +158 -0
- django_cfg/apps/knowbase/management/commands/setup_knowbase.py +59 -0
- django_cfg/apps/knowbase/managers/__init__.py +22 -0
- django_cfg/apps/knowbase/managers/archive.py +426 -0
- django_cfg/apps/knowbase/managers/base.py +32 -0
- django_cfg/apps/knowbase/managers/chat.py +141 -0
- django_cfg/apps/knowbase/managers/document.py +203 -0
- django_cfg/apps/knowbase/managers/external_data.py +471 -0
- django_cfg/apps/knowbase/migrations/0001_initial.py +427 -0
- django_cfg/apps/knowbase/migrations/0002_archiveitem_archiveitemchunk_documentarchive_and_more.py +434 -0
- django_cfg/apps/knowbase/migrations/__init__.py +5 -0
- django_cfg/apps/knowbase/mixins/__init__.py +15 -0
- django_cfg/apps/knowbase/mixins/config.py +108 -0
- django_cfg/apps/knowbase/mixins/creator.py +81 -0
- django_cfg/apps/knowbase/mixins/examples/vehicle_model_example.py +199 -0
- django_cfg/apps/knowbase/mixins/external_data_mixin.py +813 -0
- django_cfg/apps/knowbase/mixins/service.py +362 -0
- django_cfg/apps/knowbase/models/__init__.py +41 -0
- django_cfg/apps/knowbase/models/archive.py +599 -0
- django_cfg/apps/knowbase/models/base.py +58 -0
- django_cfg/apps/knowbase/models/chat.py +157 -0
- django_cfg/apps/knowbase/models/document.py +267 -0
- django_cfg/apps/knowbase/models/external_data.py +376 -0
- django_cfg/apps/knowbase/serializers/__init__.py +68 -0
- django_cfg/apps/knowbase/serializers/archive_serializers.py +386 -0
- django_cfg/apps/knowbase/serializers/chat_serializers.py +137 -0
- django_cfg/apps/knowbase/serializers/document_serializers.py +94 -0
- django_cfg/apps/knowbase/serializers/external_data_serializers.py +256 -0
- django_cfg/apps/knowbase/serializers/public_serializers.py +74 -0
- django_cfg/apps/knowbase/services/__init__.py +40 -0
- django_cfg/apps/knowbase/services/archive/__init__.py +42 -0
- django_cfg/apps/knowbase/services/archive/archive_service.py +541 -0
- django_cfg/apps/knowbase/services/archive/chunking_service.py +791 -0
- django_cfg/apps/knowbase/services/archive/exceptions.py +52 -0
- django_cfg/apps/knowbase/services/archive/extraction_service.py +508 -0
- django_cfg/apps/knowbase/services/archive/vectorization_service.py +362 -0
- django_cfg/apps/knowbase/services/base.py +53 -0
- django_cfg/apps/knowbase/services/chat_service.py +239 -0
- django_cfg/apps/knowbase/services/document_service.py +144 -0
- django_cfg/apps/knowbase/services/embedding/__init__.py +43 -0
- django_cfg/apps/knowbase/services/embedding/async_processor.py +244 -0
- django_cfg/apps/knowbase/services/embedding/batch_processor.py +250 -0
- django_cfg/apps/knowbase/services/embedding/batch_result.py +61 -0
- django_cfg/apps/knowbase/services/embedding/models.py +229 -0
- django_cfg/apps/knowbase/services/embedding/processors.py +148 -0
- django_cfg/apps/knowbase/services/embedding/utils.py +176 -0
- django_cfg/apps/knowbase/services/prompt_builder.py +191 -0
- django_cfg/apps/knowbase/services/search_service.py +293 -0
- django_cfg/apps/knowbase/signals/__init__.py +21 -0
- django_cfg/apps/knowbase/signals/archive_signals.py +211 -0
- django_cfg/apps/knowbase/signals/chat_signals.py +37 -0
- django_cfg/apps/knowbase/signals/document_signals.py +143 -0
- django_cfg/apps/knowbase/signals/external_data_signals.py +157 -0
- django_cfg/apps/knowbase/tasks/__init__.py +39 -0
- django_cfg/apps/knowbase/tasks/archive_tasks.py +316 -0
- django_cfg/apps/knowbase/tasks/document_processing.py +341 -0
- django_cfg/apps/knowbase/tasks/external_data_tasks.py +341 -0
- django_cfg/apps/knowbase/tasks/maintenance.py +195 -0
- django_cfg/apps/knowbase/urls.py +43 -0
- django_cfg/apps/knowbase/utils/__init__.py +12 -0
- django_cfg/apps/knowbase/utils/chunk_settings.py +261 -0
- django_cfg/apps/knowbase/utils/text_processing.py +375 -0
- django_cfg/apps/knowbase/utils/validation.py +99 -0
- django_cfg/apps/knowbase/views/__init__.py +28 -0
- django_cfg/apps/knowbase/views/archive_views.py +469 -0
- django_cfg/apps/knowbase/views/base.py +49 -0
- django_cfg/apps/knowbase/views/chat_views.py +181 -0
- django_cfg/apps/knowbase/views/document_views.py +183 -0
- django_cfg/apps/knowbase/views/public_views.py +129 -0
- django_cfg/apps/leads/admin.py +70 -0
- django_cfg/apps/newsletter/admin.py +234 -0
- django_cfg/apps/newsletter/admin_filters.py +124 -0
- django_cfg/apps/support/admin.py +196 -0
- django_cfg/apps/support/admin_filters.py +71 -0
- django_cfg/apps/support/templates/support/chat/ticket_chat.html +1 -1
- django_cfg/apps/urls.py +5 -4
- django_cfg/cli/README.md +1 -1
- django_cfg/cli/commands/create_project.py +2 -2
- django_cfg/cli/commands/info.py +1 -1
- django_cfg/config.py +44 -0
- django_cfg/core/config.py +29 -82
- django_cfg/core/environment.py +1 -1
- django_cfg/core/generation.py +19 -107
- django_cfg/{integration.py → core/integration.py} +18 -16
- django_cfg/core/validation.py +1 -1
- django_cfg/management/__init__.py +1 -1
- django_cfg/management/commands/__init__.py +1 -1
- django_cfg/management/commands/auto_generate.py +482 -0
- django_cfg/management/commands/migrator.py +19 -101
- django_cfg/management/commands/test_email.py +1 -1
- django_cfg/middleware/README.md +0 -158
- django_cfg/middleware/__init__.py +0 -2
- django_cfg/middleware/user_activity.py +3 -3
- django_cfg/models/api.py +145 -0
- django_cfg/models/base.py +287 -0
- django_cfg/models/cache.py +4 -4
- django_cfg/models/constance.py +25 -88
- django_cfg/models/database.py +9 -9
- django_cfg/models/drf.py +3 -36
- django_cfg/models/email.py +163 -0
- django_cfg/models/environment.py +276 -0
- django_cfg/models/limits.py +1 -1
- django_cfg/models/logging.py +366 -0
- django_cfg/models/revolution.py +41 -2
- django_cfg/models/security.py +125 -0
- django_cfg/models/services.py +1 -1
- django_cfg/modules/__init__.py +2 -56
- django_cfg/modules/base.py +78 -52
- django_cfg/modules/django_currency/service.py +2 -2
- django_cfg/modules/django_email.py +2 -2
- django_cfg/modules/django_health.py +267 -0
- django_cfg/modules/django_llm/llm/client.py +79 -17
- django_cfg/modules/django_llm/translator/translator.py +2 -2
- django_cfg/modules/django_logger.py +2 -2
- django_cfg/modules/django_ngrok.py +2 -2
- django_cfg/modules/django_tasks.py +68 -3
- django_cfg/modules/django_telegram.py +3 -3
- django_cfg/modules/django_twilio/sendgrid_service.py +2 -2
- django_cfg/modules/django_twilio/service.py +2 -2
- django_cfg/modules/django_twilio/simple_service.py +2 -2
- django_cfg/modules/django_twilio/twilio_service.py +2 -2
- django_cfg/modules/django_unfold/__init__.py +69 -0
- django_cfg/modules/{unfold → django_unfold}/callbacks.py +23 -22
- django_cfg/modules/django_unfold/dashboard.py +278 -0
- django_cfg/modules/django_unfold/icons/README.md +145 -0
- django_cfg/modules/django_unfold/icons/__init__.py +12 -0
- django_cfg/modules/django_unfold/icons/constants.py +2851 -0
- django_cfg/modules/django_unfold/icons/generate_icons.py +486 -0
- django_cfg/modules/django_unfold/models/__init__.py +42 -0
- django_cfg/modules/django_unfold/models/config.py +601 -0
- django_cfg/modules/django_unfold/models/dashboard.py +206 -0
- django_cfg/modules/django_unfold/models/dropdown.py +40 -0
- django_cfg/modules/django_unfold/models/navigation.py +73 -0
- django_cfg/modules/django_unfold/models/tabs.py +25 -0
- django_cfg/modules/{unfold → django_unfold}/system_monitor.py +2 -2
- django_cfg/modules/django_unfold/utils.py +140 -0
- django_cfg/registry/__init__.py +23 -0
- django_cfg/registry/core.py +61 -0
- django_cfg/registry/exceptions.py +11 -0
- django_cfg/registry/modules.py +12 -0
- django_cfg/registry/services.py +26 -0
- django_cfg/registry/third_party.py +52 -0
- django_cfg/routing/__init__.py +19 -0
- django_cfg/routing/callbacks.py +198 -0
- django_cfg/routing/routers.py +48 -0
- django_cfg/templates/admin/layouts/dashboard_with_tabs.html +8 -9
- django_cfg/templatetags/__init__.py +0 -0
- django_cfg/templatetags/django_cfg.py +33 -0
- django_cfg/urls.py +33 -0
- django_cfg/utils/path_resolution.py +1 -1
- django_cfg/utils/smart_defaults.py +7 -61
- django_cfg/utils/toolkit.py +663 -0
- {django_cfg-1.1.82.dist-info → django_cfg-1.2.0.dist-info}/METADATA +83 -86
- django_cfg-1.2.0.dist-info/RECORD +441 -0
- django_cfg/archive/django_sample.zip +0 -0
- django_cfg/models/unfold.py +0 -271
- django_cfg/modules/unfold/__init__.py +0 -29
- django_cfg/modules/unfold/dashboard.py +0 -318
- django_cfg/pyproject.toml +0 -370
- django_cfg/routers.py +0 -83
- django_cfg-1.1.82.dist-info/RECORD +0 -278
- /django_cfg/{exceptions.py → core/exceptions.py} +0 -0
- /django_cfg/modules/{unfold → django_unfold}/models.py +0 -0
- /django_cfg/modules/{unfold → django_unfold}/tailwind.py +0 -0
- /django_cfg/{version_check.py → utils/version_check.py} +0 -0
- {django_cfg-1.1.82.dist-info → django_cfg-1.2.0.dist-info}/WHEEL +0 -0
- {django_cfg-1.1.82.dist-info → django_cfg-1.2.0.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.1.82.dist-info → django_cfg-1.2.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,482 @@
|
|
1
|
+
"""
|
2
|
+
Auto Generation Command for Django Config Toolkit
|
3
|
+
Generate configuration files, models, and other Django components.
|
4
|
+
"""
|
5
|
+
|
6
|
+
import os
|
7
|
+
import json
|
8
|
+
from pathlib import Path
|
9
|
+
from django.core.management.base import BaseCommand
|
10
|
+
from django.core.management import call_command
|
11
|
+
from django.conf import settings
|
12
|
+
import questionary
|
13
|
+
from datetime import datetime
|
14
|
+
|
15
|
+
from django_cfg import ConfigToolkit
|
16
|
+
|
17
|
+
|
18
|
+
class Command(BaseCommand):
|
19
|
+
help = 'Auto-generate configuration files and Django components'
|
20
|
+
|
21
|
+
def add_arguments(self, parser):
|
22
|
+
parser.add_argument(
|
23
|
+
'--config',
|
24
|
+
action='store_true',
|
25
|
+
help='Generate configuration files only'
|
26
|
+
)
|
27
|
+
parser.add_argument(
|
28
|
+
'--models',
|
29
|
+
action='store_true',
|
30
|
+
help='Generate model files only'
|
31
|
+
)
|
32
|
+
parser.add_argument(
|
33
|
+
'--all',
|
34
|
+
action='store_true',
|
35
|
+
help='Generate all components'
|
36
|
+
)
|
37
|
+
|
38
|
+
def handle(self, *args, **options):
|
39
|
+
if options['all']:
|
40
|
+
self.generate_all()
|
41
|
+
elif options['config']:
|
42
|
+
self.generate_config_files()
|
43
|
+
elif options['models']:
|
44
|
+
self.generate_model_files()
|
45
|
+
else:
|
46
|
+
self.show_interactive_menu()
|
47
|
+
|
48
|
+
def show_interactive_menu(self):
|
49
|
+
"""Show interactive menu with generation options"""
|
50
|
+
self.stdout.write(self.style.SUCCESS('\n🚀 Auto Generation Tool - Django Config Toolkit\n'))
|
51
|
+
|
52
|
+
choices = [
|
53
|
+
questionary.Choice('⚙️ Generate Configuration Files', value='config'),
|
54
|
+
questionary.Choice('📊 Generate Model Files', value='models'),
|
55
|
+
questionary.Choice('🔄 Generate All Components', value='all'),
|
56
|
+
questionary.Choice('📝 Generate Environment Template', value='env'),
|
57
|
+
questionary.Choice('🔧 Generate Settings Template', value='settings'),
|
58
|
+
questionary.Choice('❌ Exit', value='exit')
|
59
|
+
]
|
60
|
+
|
61
|
+
choice = questionary.select(
|
62
|
+
'Select generation option:',
|
63
|
+
choices=choices
|
64
|
+
).ask()
|
65
|
+
|
66
|
+
if choice == 'config':
|
67
|
+
self.generate_config_files()
|
68
|
+
elif choice == 'models':
|
69
|
+
self.generate_model_files()
|
70
|
+
elif choice == 'all':
|
71
|
+
self.generate_all()
|
72
|
+
elif choice == 'env':
|
73
|
+
self.generate_env_template()
|
74
|
+
elif choice == 'settings':
|
75
|
+
self.generate_settings_template()
|
76
|
+
elif choice == 'exit':
|
77
|
+
self.stdout.write('Goodbye! 👋')
|
78
|
+
return
|
79
|
+
|
80
|
+
def generate_all(self):
|
81
|
+
"""Generate all components"""
|
82
|
+
self.stdout.write(self.style.SUCCESS('🔄 Generating all components...'))
|
83
|
+
|
84
|
+
self.generate_config_files()
|
85
|
+
self.generate_model_files()
|
86
|
+
self.generate_env_template()
|
87
|
+
self.generate_settings_template()
|
88
|
+
|
89
|
+
self.stdout.write(self.style.SUCCESS('✅ All components generated!'))
|
90
|
+
|
91
|
+
def generate_config_files(self):
|
92
|
+
"""Generate configuration files"""
|
93
|
+
self.stdout.write(self.style.SUCCESS('⚙️ Generating configuration files...'))
|
94
|
+
|
95
|
+
# Generate config.py
|
96
|
+
self.generate_config_py()
|
97
|
+
|
98
|
+
# Generate database config
|
99
|
+
self.generate_database_config()
|
100
|
+
|
101
|
+
# Generate security config
|
102
|
+
self.generate_security_config()
|
103
|
+
|
104
|
+
self.stdout.write(self.style.SUCCESS('✅ Configuration files generated!'))
|
105
|
+
|
106
|
+
def generate_model_files(self):
|
107
|
+
"""Generate model files"""
|
108
|
+
self.stdout.write(self.style.SUCCESS('📊 Generating model files...'))
|
109
|
+
|
110
|
+
# Generate base models
|
111
|
+
self.generate_base_models()
|
112
|
+
|
113
|
+
# Generate API models
|
114
|
+
self.generate_api_models()
|
115
|
+
|
116
|
+
self.stdout.write(self.style.SUCCESS('✅ Model files generated!'))
|
117
|
+
|
118
|
+
def generate_config_py(self):
|
119
|
+
"""Generate main config.py file"""
|
120
|
+
config_content = '''"""
|
121
|
+
Configuration file for Django Config Toolkit
|
122
|
+
Auto-generated configuration with smart defaults.
|
123
|
+
"""
|
124
|
+
|
125
|
+
from django_cfg import ConfigToolkit
|
126
|
+
|
127
|
+
# Initialize configuration
|
128
|
+
config = ConfigToolkit()
|
129
|
+
|
130
|
+
# Export all settings
|
131
|
+
globals().update(config.get_django_settings())
|
132
|
+
|
133
|
+
# Type-safe access to configuration
|
134
|
+
DEBUG = config.debug
|
135
|
+
SECRET_KEY = config.secret_key
|
136
|
+
DATABASE_URL = config.database_url
|
137
|
+
ALLOWED_HOSTS = config.allowed_hosts
|
138
|
+
'''
|
139
|
+
|
140
|
+
config_path = Path('config.py')
|
141
|
+
if not config_path.exists():
|
142
|
+
with open(config_path, 'w') as f:
|
143
|
+
f.write(config_content)
|
144
|
+
self.stdout.write(f' 📄 Created {config_path}')
|
145
|
+
|
146
|
+
def generate_database_config(self):
|
147
|
+
"""Generate database configuration"""
|
148
|
+
db_config_content = '''"""
|
149
|
+
Database Configuration
|
150
|
+
Auto-generated database settings.
|
151
|
+
"""
|
152
|
+
|
153
|
+
from django_cfg import DatabaseConfig
|
154
|
+
|
155
|
+
# Database configuration
|
156
|
+
db_config = DatabaseConfig(
|
157
|
+
database_url="sqlite:///db.sqlite3",
|
158
|
+
max_connections=20,
|
159
|
+
conn_max_age=600,
|
160
|
+
conn_health_checks=True,
|
161
|
+
ssl_require=False,
|
162
|
+
ssl_mode="prefer",
|
163
|
+
query_timeout=30,
|
164
|
+
)
|
165
|
+
|
166
|
+
# Additional databases (uncomment and configure as needed)
|
167
|
+
# db_config.read_replica_url = "postgresql://user:pass@host:port/db"
|
168
|
+
# db_config.cache_db_url = "redis://localhost:6379/1"
|
169
|
+
# db_config.analytics_db_url = "postgresql://user:pass@host:port/analytics"
|
170
|
+
|
171
|
+
# Export database settings
|
172
|
+
globals().update(db_config.to_django_settings())
|
173
|
+
'''
|
174
|
+
|
175
|
+
db_config_path = Path('database_config.py')
|
176
|
+
if not db_config_path.exists():
|
177
|
+
with open(db_config_path, 'w') as f:
|
178
|
+
f.write(db_config_content)
|
179
|
+
self.stdout.write(f' 📄 Created {db_config_path}')
|
180
|
+
|
181
|
+
def generate_security_config(self):
|
182
|
+
"""Generate security configuration"""
|
183
|
+
security_config_content = '''"""
|
184
|
+
Security Configuration
|
185
|
+
Auto-generated security settings.
|
186
|
+
"""
|
187
|
+
|
188
|
+
from django_cfg import SecurityConfig
|
189
|
+
|
190
|
+
# Security configuration
|
191
|
+
security_config = SecurityConfig(
|
192
|
+
secret_key="your-secret-key-here",
|
193
|
+
debug=False,
|
194
|
+
allowed_hosts=["localhost", "127.0.0.1"],
|
195
|
+
csrf_trusted_origins=["http://localhost:3000"],
|
196
|
+
cors_allowed_origins=["http://localhost:3000"],
|
197
|
+
cors_allowed_methods=["GET", "POST", "PUT", "DELETE"],
|
198
|
+
cors_allowed_headers=["*"],
|
199
|
+
)
|
200
|
+
|
201
|
+
# Export security settings
|
202
|
+
globals().update(security_config.to_django_settings())
|
203
|
+
'''
|
204
|
+
|
205
|
+
security_config_path = Path('security_config.py')
|
206
|
+
if not security_config_path.exists():
|
207
|
+
with open(security_config_path, 'w') as f:
|
208
|
+
f.write(security_config_content)
|
209
|
+
self.stdout.write(f' 📄 Created {security_config_path}')
|
210
|
+
|
211
|
+
def generate_base_models(self):
|
212
|
+
"""Generate base model files"""
|
213
|
+
base_models_content = '''"""
|
214
|
+
Base Models
|
215
|
+
Auto-generated base model classes.
|
216
|
+
"""
|
217
|
+
|
218
|
+
from django.db import models
|
219
|
+
from django.utils import timezone
|
220
|
+
|
221
|
+
|
222
|
+
class BaseModel(models.Model):
|
223
|
+
"""Base model with common fields."""
|
224
|
+
|
225
|
+
created_at = models.DateTimeField(auto_now_add=True)
|
226
|
+
updated_at = models.DateTimeField(auto_now=True)
|
227
|
+
is_active = models.BooleanField(default=True)
|
228
|
+
|
229
|
+
class Meta:
|
230
|
+
abstract = True
|
231
|
+
|
232
|
+
def __str__(self):
|
233
|
+
return f"{self.__class__.__name__} {self.id}"
|
234
|
+
|
235
|
+
|
236
|
+
class TimestampedModel(BaseModel):
|
237
|
+
"""Model with timestamps."""
|
238
|
+
|
239
|
+
created_by = models.ForeignKey(
|
240
|
+
'auth.User',
|
241
|
+
on_delete=models.SET_NULL,
|
242
|
+
null=True,
|
243
|
+
blank=True,
|
244
|
+
related_name='%(class)s_created'
|
245
|
+
)
|
246
|
+
updated_by = models.ForeignKey(
|
247
|
+
'auth.User',
|
248
|
+
on_delete=models.SET_NULL,
|
249
|
+
null=True,
|
250
|
+
blank=True,
|
251
|
+
related_name='%(class)s_updated'
|
252
|
+
)
|
253
|
+
|
254
|
+
class Meta:
|
255
|
+
abstract = True
|
256
|
+
'''
|
257
|
+
|
258
|
+
base_models_path = Path('models/base.py')
|
259
|
+
base_models_path.parent.mkdir(exist_ok=True)
|
260
|
+
|
261
|
+
if not base_models_path.exists():
|
262
|
+
with open(base_models_path, 'w') as f:
|
263
|
+
f.write(base_models_content)
|
264
|
+
self.stdout.write(f' 📄 Created {base_models_path}')
|
265
|
+
|
266
|
+
def generate_api_models(self):
|
267
|
+
"""Generate API model files"""
|
268
|
+
api_models_content = '''"""
|
269
|
+
API Models
|
270
|
+
Auto-generated API model classes.
|
271
|
+
"""
|
272
|
+
|
273
|
+
from django.db import models
|
274
|
+
from .base import BaseModel
|
275
|
+
|
276
|
+
|
277
|
+
class APIModel(BaseModel):
|
278
|
+
"""Base model for API resources."""
|
279
|
+
|
280
|
+
name = models.CharField(max_length=255)
|
281
|
+
description = models.TextField(blank=True)
|
282
|
+
slug = models.SlugField(max_length=255, unique=True)
|
283
|
+
|
284
|
+
class Meta:
|
285
|
+
abstract = True
|
286
|
+
|
287
|
+
def __str__(self):
|
288
|
+
return self.name
|
289
|
+
|
290
|
+
|
291
|
+
class ConfigModel(APIModel):
|
292
|
+
"""Configuration model for storing settings."""
|
293
|
+
|
294
|
+
key = models.CharField(max_length=255, unique=True)
|
295
|
+
value = models.JSONField()
|
296
|
+
value_type = models.CharField(
|
297
|
+
max_length=50,
|
298
|
+
choices=[
|
299
|
+
('string', 'String'),
|
300
|
+
('integer', 'Integer'),
|
301
|
+
('float', 'Float'),
|
302
|
+
('boolean', 'Boolean'),
|
303
|
+
('json', 'JSON'),
|
304
|
+
],
|
305
|
+
default='string'
|
306
|
+
)
|
307
|
+
|
308
|
+
class Meta:
|
309
|
+
verbose_name = 'Configuration'
|
310
|
+
verbose_name_plural = 'Configurations'
|
311
|
+
'''
|
312
|
+
|
313
|
+
api_models_path = Path('models/api.py')
|
314
|
+
api_models_path.parent.mkdir(exist_ok=True)
|
315
|
+
|
316
|
+
if not api_models_path.exists():
|
317
|
+
with open(api_models_path, 'w') as f:
|
318
|
+
f.write(api_models_content)
|
319
|
+
self.stdout.write(f' 📄 Created {api_models_path}')
|
320
|
+
|
321
|
+
def generate_env_template(self):
|
322
|
+
"""Generate environment template file"""
|
323
|
+
env_template_content = '''# Environment Configuration Template
|
324
|
+
# Copy this file to .env and configure your settings
|
325
|
+
|
326
|
+
# Django Settings
|
327
|
+
DEBUG=True
|
328
|
+
SECRET_KEY=your-secret-key-here
|
329
|
+
ALLOWED_HOSTS=localhost,127.0.0.1
|
330
|
+
|
331
|
+
# Database Settings
|
332
|
+
DATABASE_URL=sqlite:///db.sqlite3
|
333
|
+
# DATABASE_URL=postgresql://user:password@localhost:5432/dbname
|
334
|
+
# DATABASE_URL=mysql://user:password@localhost:3306/dbname
|
335
|
+
|
336
|
+
# Additional Databases (optional)
|
337
|
+
# DATABASE_URL_CARS=postgresql://user:password@localhost:5432/cars_db
|
338
|
+
# DATABASE_URL_ANALYTICS=postgresql://user:password@localhost:5432/analytics_db
|
339
|
+
# DATABASE_URL_CACHE=redis://localhost:6379/1
|
340
|
+
|
341
|
+
# Email Settings
|
342
|
+
EMAIL_BACKEND=django.core.mail.backends.console.EmailBackend
|
343
|
+
EMAIL_HOST=smtp.gmail.com
|
344
|
+
EMAIL_PORT=587
|
345
|
+
EMAIL_USE_TLS=True
|
346
|
+
EMAIL_HOST_USER=your-email@gmail.com
|
347
|
+
EMAIL_HOST_PASSWORD=your-app-password
|
348
|
+
|
349
|
+
# Cache Settings
|
350
|
+
CACHE_BACKEND=django.core.cache.backends.locmem.LocMemCache
|
351
|
+
# CACHE_BACKEND=django.core.cache.backends.redis.RedisCache
|
352
|
+
# CACHE_LOCATION=redis://127.0.0.1:6379/1
|
353
|
+
|
354
|
+
# Security Settings
|
355
|
+
CSRF_TRUSTED_ORIGINS=http://localhost:3000
|
356
|
+
CORS_ALLOWED_ORIGINS=http://localhost:3000
|
357
|
+
|
358
|
+
# API Settings
|
359
|
+
API_KEY=your-api-key-here
|
360
|
+
API_RATE_LIMIT=1000
|
361
|
+
|
362
|
+
# Logging Settings
|
363
|
+
LOG_LEVEL=INFO
|
364
|
+
LOG_FILE=logs/app.log
|
365
|
+
'''
|
366
|
+
|
367
|
+
env_template_path = Path('.env.template')
|
368
|
+
if not env_template_path.exists():
|
369
|
+
with open(env_template_path, 'w') as f:
|
370
|
+
f.write(env_template_content)
|
371
|
+
self.stdout.write(f' 📄 Created {env_template_path}')
|
372
|
+
|
373
|
+
def generate_settings_template(self):
|
374
|
+
"""Generate Django settings template"""
|
375
|
+
settings_template_content = '''"""
|
376
|
+
Django Settings Template
|
377
|
+
Auto-generated Django settings with Django Config Toolkit.
|
378
|
+
"""
|
379
|
+
|
380
|
+
import os
|
381
|
+
from pathlib import Path
|
382
|
+
|
383
|
+
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
384
|
+
BASE_DIR = Path(__file__).resolve().parent.parent
|
385
|
+
|
386
|
+
# Import configuration from Django Config Toolkit
|
387
|
+
from django_cfg import ConfigToolkit
|
388
|
+
|
389
|
+
# Initialize configuration
|
390
|
+
config = ConfigToolkit()
|
391
|
+
|
392
|
+
# Export all settings
|
393
|
+
globals().update(config.get_django_settings())
|
394
|
+
|
395
|
+
# Application definition
|
396
|
+
INSTALLED_APPS = [
|
397
|
+
'django.contrib.admin',
|
398
|
+
'django.contrib.auth',
|
399
|
+
'django.contrib.contenttypes',
|
400
|
+
'django.contrib.sessions',
|
401
|
+
'django.contrib.messages',
|
402
|
+
'django.contrib.staticfiles',
|
403
|
+
|
404
|
+
# Third party apps
|
405
|
+
'rest_framework',
|
406
|
+
'corsheaders',
|
407
|
+
'django_cfg',
|
408
|
+
|
409
|
+
# Local apps
|
410
|
+
# Add your apps here
|
411
|
+
]
|
412
|
+
|
413
|
+
MIDDLEWARE = [
|
414
|
+
'corsheaders.middleware.CorsMiddleware',
|
415
|
+
'django.middleware.security.SecurityMiddleware',
|
416
|
+
'django.contrib.sessions.middleware.SessionMiddleware',
|
417
|
+
'django.middleware.common.CommonMiddleware',
|
418
|
+
'django.middleware.csrf.CsrfViewMiddleware',
|
419
|
+
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
420
|
+
'django.contrib.messages.middleware.MessageMiddleware',
|
421
|
+
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
422
|
+
]
|
423
|
+
|
424
|
+
ROOT_URLCONF = 'project.urls'
|
425
|
+
|
426
|
+
TEMPLATES = [
|
427
|
+
{
|
428
|
+
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
429
|
+
'DIRS': [BASE_DIR / 'templates'],
|
430
|
+
'APP_DIRS': True,
|
431
|
+
'OPTIONS': {
|
432
|
+
'context_processors': [
|
433
|
+
'django.template.context_processors.debug',
|
434
|
+
'django.template.context_processors.request',
|
435
|
+
'django.contrib.auth.context_processors.auth',
|
436
|
+
'django.contrib.messages.context_processors.messages',
|
437
|
+
],
|
438
|
+
},
|
439
|
+
},
|
440
|
+
]
|
441
|
+
|
442
|
+
WSGI_APPLICATION = 'project.wsgi.application'
|
443
|
+
|
444
|
+
# Static files (CSS, JavaScript, Images)
|
445
|
+
STATIC_URL = '/static/'
|
446
|
+
STATIC_ROOT = BASE_DIR / 'staticfiles'
|
447
|
+
STATICFILES_DIRS = [BASE_DIR / 'static']
|
448
|
+
|
449
|
+
# Media files
|
450
|
+
MEDIA_URL = '/media/'
|
451
|
+
MEDIA_ROOT = BASE_DIR / 'media'
|
452
|
+
|
453
|
+
# Default primary key field type
|
454
|
+
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
455
|
+
|
456
|
+
# REST Framework settings
|
457
|
+
REST_FRAMEWORK = {
|
458
|
+
'DEFAULT_AUTHENTICATION_CLASSES': [
|
459
|
+
'rest_framework.authentication.SessionAuthentication',
|
460
|
+
'rest_framework.authentication.TokenAuthentication',
|
461
|
+
],
|
462
|
+
'DEFAULT_PERMISSION_CLASSES': [
|
463
|
+
'rest_framework.permissions.IsAuthenticated',
|
464
|
+
],
|
465
|
+
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
|
466
|
+
'PAGE_SIZE': 20,
|
467
|
+
}
|
468
|
+
|
469
|
+
# Health check URLs
|
470
|
+
HEALTH_CHECK_URLS = [
|
471
|
+
'health/',
|
472
|
+
'health/detailed/',
|
473
|
+
'ready/',
|
474
|
+
'alive/',
|
475
|
+
]
|
476
|
+
'''
|
477
|
+
|
478
|
+
settings_template_path = Path('settings_template.py')
|
479
|
+
if not settings_template_path.exists():
|
480
|
+
with open(settings_template_path, 'w') as f:
|
481
|
+
f.write(settings_template_content)
|
482
|
+
self.stdout.write(f' 📄 Created {settings_template_path}')
|
@@ -143,16 +143,13 @@ class Command(BaseCommand):
|
|
143
143
|
# Migrate each app
|
144
144
|
for app in apps:
|
145
145
|
try:
|
146
|
-
# Convert full module path to app_label if needed
|
147
|
-
app_label = self.get_app_label_from_path(app)
|
148
|
-
|
149
146
|
# Skip apps without migrations
|
150
|
-
if not self.app_has_migrations(
|
151
|
-
# self.stdout.write(f" ⚠️ Skipping {
|
147
|
+
if not self.app_has_migrations(app):
|
148
|
+
# self.stdout.write(f" ⚠️ Skipping {app} - no migrations")
|
152
149
|
continue
|
153
150
|
|
154
|
-
self.stdout.write(f" 📦 Migrating {
|
155
|
-
call_command("migrate",
|
151
|
+
self.stdout.write(f" 📦 Migrating {app}...")
|
152
|
+
call_command("migrate", app, database=db_name, verbosity=1)
|
156
153
|
except Exception as e:
|
157
154
|
self.stdout.write(self.style.WARNING(f" ⚠️ Warning migrating {app}: {e}"))
|
158
155
|
|
@@ -188,11 +185,9 @@ class Command(BaseCommand):
|
|
188
185
|
for db_name in databases:
|
189
186
|
apps = self.get_apps_for_database(db_name)
|
190
187
|
if app_name in apps:
|
191
|
-
|
192
|
-
app_label = self.get_app_label_from_path(app_name)
|
193
|
-
self.stdout.write(f" 📊 Migrating {app_label} on {db_name}...")
|
188
|
+
self.stdout.write(f" 📊 Migrating {app_name} on {db_name}...")
|
194
189
|
try:
|
195
|
-
call_command("migrate",
|
190
|
+
call_command("migrate", app_name, database=db_name, verbosity=1)
|
196
191
|
except Exception as e:
|
197
192
|
self.stdout.write(self.style.WARNING(f" ⚠️ Warning: {e}"))
|
198
193
|
|
@@ -270,43 +265,19 @@ class Command(BaseCommand):
|
|
270
265
|
self.stdout.write(self.style.ERROR(f"❌ Error getting Django config info: {e}"))
|
271
266
|
|
272
267
|
def get_apps_for_database(self, db_name: str):
|
273
|
-
"""Get apps for specific database
|
274
|
-
try:
|
275
|
-
# Try to get Django-CFG config
|
276
|
-
from django_cfg.core.config import get_current_config
|
277
|
-
config = get_current_config()
|
278
|
-
|
279
|
-
if config and hasattr(config, 'databases'):
|
280
|
-
if db_name in config.databases:
|
281
|
-
db_config = config.databases[db_name]
|
282
|
-
if hasattr(db_config, 'apps') and db_config.apps:
|
283
|
-
return db_config.apps
|
284
|
-
|
285
|
-
# For default database, get all apps not in other databases
|
286
|
-
if db_name == "default":
|
287
|
-
all_apps = self.get_all_installed_apps()
|
288
|
-
apps_in_other_dbs = set()
|
289
|
-
|
290
|
-
# Collect apps from all non-default databases
|
291
|
-
for other_db_name, other_db_config in config.databases.items():
|
292
|
-
if other_db_name != "default" and hasattr(other_db_config, 'apps'):
|
293
|
-
# Convert full paths to app_labels for comparison
|
294
|
-
for app_path in other_db_config.apps:
|
295
|
-
app_label = self.get_app_label_from_path(app_path)
|
296
|
-
apps_in_other_dbs.add(app_label)
|
297
|
-
|
298
|
-
return [app for app in all_apps if app not in apps_in_other_dbs]
|
299
|
-
|
300
|
-
except Exception as e:
|
301
|
-
self.stdout.write(self.style.WARNING(f"⚠️ Could not get Django-CFG config: {e}"))
|
302
|
-
|
303
|
-
# Fallback to old routing rules method
|
304
|
-
routing_rules = getattr(settings, "DATABASE_ROUTING_RULES", {})
|
268
|
+
"""Get apps for specific database with smart logic for default"""
|
305
269
|
if db_name == "default":
|
270
|
+
# For default database, get all apps that are not in other databases
|
306
271
|
all_apps = self.get_all_installed_apps()
|
307
|
-
apps_in_other_dbs =
|
272
|
+
apps_in_other_dbs = self.get_apps_in_other_databases()
|
308
273
|
return [app for app in all_apps if app not in apps_in_other_dbs]
|
309
274
|
else:
|
275
|
+
# For other databases, use configured apps from routing rules
|
276
|
+
routing_rules = getattr(settings, "DATABASE_ROUTING_RULES", {})
|
277
|
+
|
278
|
+
# Routing rules are now in Django settings
|
279
|
+
pass
|
280
|
+
|
310
281
|
return [app for app, db in routing_rules.items() if db == db_name]
|
311
282
|
|
312
283
|
def get_all_installed_apps(self):
|
@@ -333,26 +304,11 @@ class Command(BaseCommand):
|
|
333
304
|
|
334
305
|
def get_apps_in_other_databases(self) -> set:
|
335
306
|
"""Get all apps that are configured for non-default databases."""
|
336
|
-
try:
|
337
|
-
# Try to get Django-CFG config
|
338
|
-
from django_cfg.core.config import get_current_config
|
339
|
-
config = get_current_config()
|
340
|
-
|
341
|
-
if config and hasattr(config, 'databases'):
|
342
|
-
apps_in_other_dbs = set()
|
343
|
-
|
344
|
-
# Collect apps from all non-default databases
|
345
|
-
for db_name, db_config in config.databases.items():
|
346
|
-
if db_name != "default" and hasattr(db_config, 'apps'):
|
347
|
-
apps_in_other_dbs.update(db_config.apps)
|
348
|
-
|
349
|
-
return apps_in_other_dbs
|
350
|
-
|
351
|
-
except Exception:
|
352
|
-
pass
|
353
|
-
|
354
|
-
# Fallback to old routing rules method
|
355
307
|
routing_rules = getattr(settings, "DATABASE_ROUTING_RULES", {})
|
308
|
+
|
309
|
+
# Routing rules are now in Django settings
|
310
|
+
pass
|
311
|
+
|
356
312
|
return set(routing_rules.keys())
|
357
313
|
|
358
314
|
def get_all_database_names(self):
|
@@ -432,41 +388,3 @@ class Command(BaseCommand):
|
|
432
388
|
except Exception:
|
433
389
|
# Silently return False for apps that don't exist or have issues
|
434
390
|
return False
|
435
|
-
|
436
|
-
def get_app_label_from_path(self, app_path: str) -> str:
|
437
|
-
"""
|
438
|
-
Convert full module path to Django app_label.
|
439
|
-
|
440
|
-
Args:
|
441
|
-
app_path: Full module path (e.g., 'apps.vehicles_data') or app_label (e.g., 'vehicles_data')
|
442
|
-
|
443
|
-
Returns:
|
444
|
-
Django app_label that can be used with migrate command
|
445
|
-
|
446
|
-
Examples:
|
447
|
-
'apps.vehicles_data' -> 'vehicles_data'
|
448
|
-
'vehicles_data' -> 'vehicles_data'
|
449
|
-
'myproject.apps.blog' -> 'blog'
|
450
|
-
"""
|
451
|
-
try:
|
452
|
-
# Try to get app config by full path first
|
453
|
-
try:
|
454
|
-
app_config = apps.get_app_config(app_path)
|
455
|
-
return app_config.label
|
456
|
-
except LookupError:
|
457
|
-
pass
|
458
|
-
|
459
|
-
# Fallback: extract last part of the path as potential app_label
|
460
|
-
potential_label = app_path.split('.')[-1]
|
461
|
-
try:
|
462
|
-
app_config = apps.get_app_config(potential_label)
|
463
|
-
return app_config.label
|
464
|
-
except LookupError:
|
465
|
-
pass
|
466
|
-
|
467
|
-
# If all fails, return original path
|
468
|
-
return app_path
|
469
|
-
|
470
|
-
except Exception:
|
471
|
-
# Fallback to original path
|
472
|
-
return app_path
|
@@ -71,7 +71,7 @@ class Command(BaseCommand):
|
|
71
71
|
'main_text': message,
|
72
72
|
'project_name': 'Django CFG Sample',
|
73
73
|
'site_url': 'http://localhost:8000',
|
74
|
-
'logo_url': 'https://
|
74
|
+
'logo_url': 'https://djangocfg.com/favicon.png',
|
75
75
|
'button_text': 'Visit Website',
|
76
76
|
'button_url': 'http://localhost:8000',
|
77
77
|
'secondary_text': 'This is a test email sent from django-cfg management command.',
|