django-cfg 1.1.82__py3-none-any.whl → 1.2.1__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.
Files changed (244) hide show
  1. django_cfg/__init__.py +20 -448
  2. django_cfg/apps/accounts/README.md +3 -3
  3. django_cfg/apps/accounts/admin/__init__.py +0 -2
  4. django_cfg/apps/accounts/admin/activity.py +2 -9
  5. django_cfg/apps/accounts/admin/filters.py +0 -42
  6. django_cfg/apps/accounts/admin/inlines.py +8 -8
  7. django_cfg/apps/accounts/admin/otp.py +5 -5
  8. django_cfg/apps/accounts/admin/registration_source.py +1 -8
  9. django_cfg/apps/accounts/admin/user.py +12 -20
  10. django_cfg/apps/accounts/managers/user_manager.py +2 -129
  11. django_cfg/apps/accounts/migrations/0006_remove_twilioresponse_otp_secret_and_more.py +46 -0
  12. django_cfg/apps/accounts/models.py +3 -123
  13. django_cfg/apps/accounts/serializers/otp.py +40 -44
  14. django_cfg/apps/accounts/serializers/profile.py +0 -2
  15. django_cfg/apps/accounts/services/otp_service.py +98 -186
  16. django_cfg/apps/accounts/signals.py +25 -15
  17. django_cfg/apps/accounts/utils/auth_email_service.py +84 -0
  18. django_cfg/apps/accounts/views/otp.py +35 -36
  19. django_cfg/apps/agents/README.md +129 -0
  20. django_cfg/apps/agents/__init__.py +68 -0
  21. django_cfg/apps/agents/admin/__init__.py +17 -0
  22. django_cfg/apps/agents/admin/execution_admin.py +460 -0
  23. django_cfg/apps/agents/admin/registry_admin.py +360 -0
  24. django_cfg/apps/agents/admin/toolsets_admin.py +482 -0
  25. django_cfg/apps/agents/apps.py +29 -0
  26. django_cfg/apps/agents/core/__init__.py +20 -0
  27. django_cfg/apps/agents/core/agent.py +281 -0
  28. django_cfg/apps/agents/core/dependencies.py +154 -0
  29. django_cfg/apps/agents/core/exceptions.py +66 -0
  30. django_cfg/apps/agents/core/models.py +106 -0
  31. django_cfg/apps/agents/core/orchestrator.py +391 -0
  32. django_cfg/apps/agents/examples/__init__.py +3 -0
  33. django_cfg/apps/agents/examples/simple_example.py +161 -0
  34. django_cfg/apps/agents/integration/__init__.py +14 -0
  35. django_cfg/apps/agents/integration/middleware.py +80 -0
  36. django_cfg/apps/agents/integration/registry.py +345 -0
  37. django_cfg/apps/agents/integration/signals.py +50 -0
  38. django_cfg/apps/agents/management/__init__.py +3 -0
  39. django_cfg/apps/agents/management/commands/__init__.py +3 -0
  40. django_cfg/apps/agents/management/commands/create_agent.py +365 -0
  41. django_cfg/apps/agents/management/commands/orchestrator_status.py +191 -0
  42. django_cfg/apps/agents/managers/__init__.py +23 -0
  43. django_cfg/apps/agents/managers/execution.py +236 -0
  44. django_cfg/apps/agents/managers/registry.py +254 -0
  45. django_cfg/apps/agents/managers/toolsets.py +496 -0
  46. django_cfg/apps/agents/migrations/0001_initial.py +286 -0
  47. django_cfg/apps/agents/migrations/__init__.py +5 -0
  48. django_cfg/apps/agents/models/__init__.py +15 -0
  49. django_cfg/apps/agents/models/execution.py +215 -0
  50. django_cfg/apps/agents/models/registry.py +220 -0
  51. django_cfg/apps/agents/models/toolsets.py +305 -0
  52. django_cfg/apps/agents/patterns/__init__.py +24 -0
  53. django_cfg/apps/agents/patterns/content_agents.py +234 -0
  54. django_cfg/apps/agents/toolsets/__init__.py +15 -0
  55. django_cfg/apps/agents/toolsets/cache_toolset.py +285 -0
  56. django_cfg/apps/agents/toolsets/django_toolset.py +220 -0
  57. django_cfg/apps/agents/toolsets/file_toolset.py +324 -0
  58. django_cfg/apps/agents/toolsets/orm_toolset.py +319 -0
  59. django_cfg/apps/agents/urls.py +46 -0
  60. django_cfg/apps/knowbase/README.md +150 -0
  61. django_cfg/apps/knowbase/__init__.py +27 -0
  62. django_cfg/apps/knowbase/admin/__init__.py +23 -0
  63. django_cfg/apps/knowbase/admin/archive_admin.py +857 -0
  64. django_cfg/apps/knowbase/admin/chat_admin.py +386 -0
  65. django_cfg/apps/knowbase/admin/document_admin.py +650 -0
  66. django_cfg/apps/knowbase/admin/external_data_admin.py +685 -0
  67. django_cfg/apps/knowbase/apps.py +81 -0
  68. django_cfg/apps/knowbase/config/README.md +176 -0
  69. django_cfg/apps/knowbase/config/__init__.py +51 -0
  70. django_cfg/apps/knowbase/config/constance_fields.py +186 -0
  71. django_cfg/apps/knowbase/config/constance_settings.py +200 -0
  72. django_cfg/apps/knowbase/config/settings.py +450 -0
  73. django_cfg/apps/knowbase/examples/__init__.py +3 -0
  74. django_cfg/apps/knowbase/examples/external_data_usage.py +191 -0
  75. django_cfg/apps/knowbase/management/__init__.py +0 -0
  76. django_cfg/apps/knowbase/management/commands/__init__.py +0 -0
  77. django_cfg/apps/knowbase/management/commands/knowbase_stats.py +158 -0
  78. django_cfg/apps/knowbase/management/commands/setup_knowbase.py +59 -0
  79. django_cfg/apps/knowbase/managers/__init__.py +22 -0
  80. django_cfg/apps/knowbase/managers/archive.py +426 -0
  81. django_cfg/apps/knowbase/managers/base.py +32 -0
  82. django_cfg/apps/knowbase/managers/chat.py +141 -0
  83. django_cfg/apps/knowbase/managers/document.py +203 -0
  84. django_cfg/apps/knowbase/managers/external_data.py +471 -0
  85. django_cfg/apps/knowbase/migrations/0001_initial.py +427 -0
  86. django_cfg/apps/knowbase/migrations/0002_archiveitem_archiveitemchunk_documentarchive_and_more.py +434 -0
  87. django_cfg/apps/knowbase/migrations/__init__.py +5 -0
  88. django_cfg/apps/knowbase/mixins/__init__.py +15 -0
  89. django_cfg/apps/knowbase/mixins/config.py +108 -0
  90. django_cfg/apps/knowbase/mixins/creator.py +81 -0
  91. django_cfg/apps/knowbase/mixins/examples/vehicle_model_example.py +199 -0
  92. django_cfg/apps/knowbase/mixins/external_data_mixin.py +813 -0
  93. django_cfg/apps/knowbase/mixins/service.py +362 -0
  94. django_cfg/apps/knowbase/models/__init__.py +41 -0
  95. django_cfg/apps/knowbase/models/archive.py +599 -0
  96. django_cfg/apps/knowbase/models/base.py +58 -0
  97. django_cfg/apps/knowbase/models/chat.py +157 -0
  98. django_cfg/apps/knowbase/models/document.py +267 -0
  99. django_cfg/apps/knowbase/models/external_data.py +376 -0
  100. django_cfg/apps/knowbase/serializers/__init__.py +68 -0
  101. django_cfg/apps/knowbase/serializers/archive_serializers.py +386 -0
  102. django_cfg/apps/knowbase/serializers/chat_serializers.py +137 -0
  103. django_cfg/apps/knowbase/serializers/document_serializers.py +94 -0
  104. django_cfg/apps/knowbase/serializers/external_data_serializers.py +256 -0
  105. django_cfg/apps/knowbase/serializers/public_serializers.py +74 -0
  106. django_cfg/apps/knowbase/services/__init__.py +40 -0
  107. django_cfg/apps/knowbase/services/archive/__init__.py +42 -0
  108. django_cfg/apps/knowbase/services/archive/archive_service.py +541 -0
  109. django_cfg/apps/knowbase/services/archive/chunking_service.py +791 -0
  110. django_cfg/apps/knowbase/services/archive/exceptions.py +52 -0
  111. django_cfg/apps/knowbase/services/archive/extraction_service.py +508 -0
  112. django_cfg/apps/knowbase/services/archive/vectorization_service.py +362 -0
  113. django_cfg/apps/knowbase/services/base.py +53 -0
  114. django_cfg/apps/knowbase/services/chat_service.py +239 -0
  115. django_cfg/apps/knowbase/services/document_service.py +144 -0
  116. django_cfg/apps/knowbase/services/embedding/__init__.py +43 -0
  117. django_cfg/apps/knowbase/services/embedding/async_processor.py +244 -0
  118. django_cfg/apps/knowbase/services/embedding/batch_processor.py +250 -0
  119. django_cfg/apps/knowbase/services/embedding/batch_result.py +61 -0
  120. django_cfg/apps/knowbase/services/embedding/models.py +229 -0
  121. django_cfg/apps/knowbase/services/embedding/processors.py +148 -0
  122. django_cfg/apps/knowbase/services/embedding/utils.py +176 -0
  123. django_cfg/apps/knowbase/services/prompt_builder.py +191 -0
  124. django_cfg/apps/knowbase/services/search_service.py +293 -0
  125. django_cfg/apps/knowbase/signals/__init__.py +21 -0
  126. django_cfg/apps/knowbase/signals/archive_signals.py +211 -0
  127. django_cfg/apps/knowbase/signals/chat_signals.py +37 -0
  128. django_cfg/apps/knowbase/signals/document_signals.py +143 -0
  129. django_cfg/apps/knowbase/signals/external_data_signals.py +157 -0
  130. django_cfg/apps/knowbase/tasks/__init__.py +39 -0
  131. django_cfg/apps/knowbase/tasks/archive_tasks.py +316 -0
  132. django_cfg/apps/knowbase/tasks/document_processing.py +341 -0
  133. django_cfg/apps/knowbase/tasks/external_data_tasks.py +341 -0
  134. django_cfg/apps/knowbase/tasks/maintenance.py +195 -0
  135. django_cfg/apps/knowbase/urls.py +43 -0
  136. django_cfg/apps/knowbase/utils/__init__.py +12 -0
  137. django_cfg/apps/knowbase/utils/chunk_settings.py +261 -0
  138. django_cfg/apps/knowbase/utils/text_processing.py +375 -0
  139. django_cfg/apps/knowbase/utils/validation.py +99 -0
  140. django_cfg/apps/knowbase/views/__init__.py +28 -0
  141. django_cfg/apps/knowbase/views/archive_views.py +469 -0
  142. django_cfg/apps/knowbase/views/base.py +49 -0
  143. django_cfg/apps/knowbase/views/chat_views.py +181 -0
  144. django_cfg/apps/knowbase/views/document_views.py +183 -0
  145. django_cfg/apps/knowbase/views/public_views.py +129 -0
  146. django_cfg/apps/leads/admin.py +70 -0
  147. django_cfg/apps/newsletter/admin.py +234 -0
  148. django_cfg/apps/newsletter/admin_filters.py +124 -0
  149. django_cfg/apps/support/admin.py +196 -0
  150. django_cfg/apps/support/admin_filters.py +71 -0
  151. django_cfg/apps/support/templates/support/chat/ticket_chat.html +1 -1
  152. django_cfg/apps/urls.py +5 -4
  153. django_cfg/cli/README.md +1 -1
  154. django_cfg/cli/commands/create_project.py +2 -2
  155. django_cfg/cli/commands/info.py +1 -1
  156. django_cfg/config.py +44 -0
  157. django_cfg/core/config.py +29 -82
  158. django_cfg/core/environment.py +1 -1
  159. django_cfg/core/generation.py +19 -107
  160. django_cfg/{integration.py → core/integration.py} +18 -16
  161. django_cfg/core/validation.py +1 -1
  162. django_cfg/management/__init__.py +1 -1
  163. django_cfg/management/commands/__init__.py +1 -1
  164. django_cfg/management/commands/auto_generate.py +482 -0
  165. django_cfg/management/commands/migrator.py +19 -101
  166. django_cfg/management/commands/test_email.py +1 -1
  167. django_cfg/middleware/README.md +0 -158
  168. django_cfg/middleware/__init__.py +0 -2
  169. django_cfg/middleware/user_activity.py +3 -3
  170. django_cfg/models/api.py +145 -0
  171. django_cfg/models/base.py +287 -0
  172. django_cfg/models/cache.py +4 -4
  173. django_cfg/models/constance.py +25 -88
  174. django_cfg/models/database.py +9 -9
  175. django_cfg/models/drf.py +3 -36
  176. django_cfg/models/email.py +163 -0
  177. django_cfg/models/environment.py +276 -0
  178. django_cfg/models/limits.py +1 -1
  179. django_cfg/models/logging.py +366 -0
  180. django_cfg/models/revolution.py +41 -2
  181. django_cfg/models/security.py +125 -0
  182. django_cfg/models/services.py +1 -1
  183. django_cfg/modules/__init__.py +2 -56
  184. django_cfg/modules/base.py +78 -52
  185. django_cfg/modules/django_currency/service.py +2 -2
  186. django_cfg/modules/django_email.py +2 -2
  187. django_cfg/modules/django_health.py +267 -0
  188. django_cfg/modules/django_llm/llm/client.py +91 -19
  189. django_cfg/modules/django_llm/translator/translator.py +2 -2
  190. django_cfg/modules/django_logger.py +2 -2
  191. django_cfg/modules/django_ngrok.py +2 -2
  192. django_cfg/modules/django_tasks.py +68 -3
  193. django_cfg/modules/django_telegram.py +3 -3
  194. django_cfg/modules/django_twilio/sendgrid_service.py +2 -2
  195. django_cfg/modules/django_twilio/service.py +2 -2
  196. django_cfg/modules/django_twilio/simple_service.py +2 -2
  197. django_cfg/modules/django_twilio/twilio_service.py +2 -2
  198. django_cfg/modules/django_unfold/__init__.py +69 -0
  199. django_cfg/modules/{unfold → django_unfold}/callbacks.py +23 -22
  200. django_cfg/modules/django_unfold/dashboard.py +278 -0
  201. django_cfg/modules/django_unfold/icons/README.md +145 -0
  202. django_cfg/modules/django_unfold/icons/__init__.py +12 -0
  203. django_cfg/modules/django_unfold/icons/constants.py +2851 -0
  204. django_cfg/modules/django_unfold/icons/generate_icons.py +486 -0
  205. django_cfg/modules/django_unfold/models/__init__.py +42 -0
  206. django_cfg/modules/django_unfold/models/config.py +601 -0
  207. django_cfg/modules/django_unfold/models/dashboard.py +206 -0
  208. django_cfg/modules/django_unfold/models/dropdown.py +40 -0
  209. django_cfg/modules/django_unfold/models/navigation.py +73 -0
  210. django_cfg/modules/django_unfold/models/tabs.py +25 -0
  211. django_cfg/modules/{unfold → django_unfold}/system_monitor.py +2 -2
  212. django_cfg/modules/django_unfold/utils.py +140 -0
  213. django_cfg/registry/__init__.py +23 -0
  214. django_cfg/registry/core.py +61 -0
  215. django_cfg/registry/exceptions.py +11 -0
  216. django_cfg/registry/modules.py +12 -0
  217. django_cfg/registry/services.py +26 -0
  218. django_cfg/registry/third_party.py +52 -0
  219. django_cfg/routing/__init__.py +19 -0
  220. django_cfg/routing/callbacks.py +198 -0
  221. django_cfg/routing/routers.py +48 -0
  222. django_cfg/templates/admin/layouts/dashboard_with_tabs.html +8 -9
  223. django_cfg/templatetags/__init__.py +0 -0
  224. django_cfg/templatetags/django_cfg.py +33 -0
  225. django_cfg/urls.py +33 -0
  226. django_cfg/utils/path_resolution.py +1 -1
  227. django_cfg/utils/smart_defaults.py +7 -61
  228. django_cfg/utils/toolkit.py +663 -0
  229. {django_cfg-1.1.82.dist-info → django_cfg-1.2.1.dist-info}/METADATA +83 -86
  230. django_cfg-1.2.1.dist-info/RECORD +441 -0
  231. django_cfg/archive/django_sample.zip +0 -0
  232. django_cfg/models/unfold.py +0 -271
  233. django_cfg/modules/unfold/__init__.py +0 -29
  234. django_cfg/modules/unfold/dashboard.py +0 -318
  235. django_cfg/pyproject.toml +0 -370
  236. django_cfg/routers.py +0 -83
  237. django_cfg-1.1.82.dist-info/RECORD +0 -278
  238. /django_cfg/{exceptions.py → core/exceptions.py} +0 -0
  239. /django_cfg/modules/{unfold → django_unfold}/models.py +0 -0
  240. /django_cfg/modules/{unfold → django_unfold}/tailwind.py +0 -0
  241. /django_cfg/{version_check.py → utils/version_check.py} +0 -0
  242. {django_cfg-1.1.82.dist-info → django_cfg-1.2.1.dist-info}/WHEEL +0 -0
  243. {django_cfg-1.1.82.dist-info → django_cfg-1.2.1.dist-info}/entry_points.txt +0 -0
  244. {django_cfg-1.1.82.dist-info → django_cfg-1.2.1.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(app_label):
151
- # self.stdout.write(f" ⚠️ Skipping {app_label} - no migrations")
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 {app_label}...")
155
- call_command("migrate", app_label, database=db_name, verbosity=1)
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
- # Convert full module path to app_label if needed
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", app_label, database=db_name, verbosity=1)
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 using Django-CFG configuration"""
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 = set(routing_rules.keys())
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://unrealos.com/favicon.png',
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.',