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.
- 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 +450 -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 +91 -19
- 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.1.dist-info}/METADATA +83 -86
- django_cfg-1.2.1.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.1.dist-info}/WHEEL +0 -0
- {django_cfg-1.1.82.dist-info → django_cfg-1.2.1.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.1.82.dist-info → django_cfg-1.2.1.dist-info}/licenses/LICENSE +0 -0
@@ -219,7 +219,7 @@ docker-compose -f docker-compose.yml -f docker-compose.nginx.yml up -d
|
|
219
219
|
|
220
220
|
- **Admin Interface**: `http://localhost:8000/admin/`
|
221
221
|
- **API Documentation**: `http://localhost:8000/api/schema/swagger-ui/`
|
222
|
-
- **Django CFG Docs**: [
|
222
|
+
- **Django CFG Docs**: [djangocfg.com](https://djangocfg.com)
|
223
223
|
|
224
224
|
## 🛠️ Development
|
225
225
|
|
@@ -579,7 +579,7 @@ def create_project(project_name: str, path: str, no_deps: bool, use_pip: bool, f
|
|
579
579
|
click.echo(" ⚡ Background task processing")
|
580
580
|
click.echo(" 🐳 Docker deployment ready")
|
581
581
|
|
582
|
-
# click.echo(f"\n📚 Documentation: https://
|
582
|
+
# click.echo(f"\n📚 Documentation: https://djangocfg.com")
|
583
583
|
|
584
584
|
# Beautiful thank you message
|
585
585
|
show_thank_you_message()
|
django_cfg/cli/commands/info.py
CHANGED
@@ -119,7 +119,7 @@ def info(verbose: bool):
|
|
119
119
|
click.echo(" # Install optional dependencies")
|
120
120
|
click.echo(" pip install twilio sendgrid django-unfold")
|
121
121
|
click.echo()
|
122
|
-
click.echo("📚 Documentation: https://
|
122
|
+
click.echo("📚 Documentation: https://djangocfg.com")
|
123
123
|
click.echo("🐙 GitHub: https://github.com/unrealos/django-cfg")
|
124
124
|
|
125
125
|
# Warnings for missing critical dependencies
|
django_cfg/config.py
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
"""
|
2
|
+
Django-CFG Library Configuration
|
3
|
+
|
4
|
+
Configuration settings for the django-cfg library itself.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from typing import List
|
8
|
+
from .modules.django_unfold.icons import Icons
|
9
|
+
from .modules.django_unfold.models.dropdown import SiteDropdownItem
|
10
|
+
|
11
|
+
|
12
|
+
# Library configuration
|
13
|
+
LIB_NAME = "Django CFG"
|
14
|
+
LIB_SITE_URL = "https://djangocfg.com"
|
15
|
+
LIB_DOCS_URL = "https://docs.djangocfg.com"
|
16
|
+
LIB_GITHUB_URL = "https://github.com/django-cfg/django-cfg"
|
17
|
+
LIB_SUPPORT_URL = "https://djangocfg.com/support"
|
18
|
+
LIB_HEALTH_URL = "/cfg/health/"
|
19
|
+
|
20
|
+
|
21
|
+
def get_default_dropdown_items() -> List[SiteDropdownItem]:
|
22
|
+
"""Get default dropdown menu items for Unfold admin."""
|
23
|
+
return [
|
24
|
+
SiteDropdownItem(
|
25
|
+
title="Documentation",
|
26
|
+
icon=Icons.HELP_OUTLINE,
|
27
|
+
link=LIB_DOCS_URL,
|
28
|
+
),
|
29
|
+
SiteDropdownItem(
|
30
|
+
title="GitHub",
|
31
|
+
icon=Icons.CODE,
|
32
|
+
link=LIB_GITHUB_URL,
|
33
|
+
),
|
34
|
+
SiteDropdownItem(
|
35
|
+
title="Support",
|
36
|
+
icon=Icons.SUPPORT_AGENT,
|
37
|
+
link=LIB_SUPPORT_URL,
|
38
|
+
),
|
39
|
+
SiteDropdownItem(
|
40
|
+
title="Django-CFG",
|
41
|
+
icon=Icons.HOME,
|
42
|
+
link=LIB_SITE_URL,
|
43
|
+
),
|
44
|
+
]
|
django_cfg/core/config.py
CHANGED
@@ -15,16 +15,11 @@ import os
|
|
15
15
|
from pathlib import Path
|
16
16
|
from urllib.parse import urlparse
|
17
17
|
|
18
|
-
from django_cfg
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
from django_cfg.models.drf import DRFConfig, SpectacularConfig
|
24
|
-
from django_cfg.models.limits import LimitsConfig
|
25
|
-
from django_cfg.models.ngrok import NgrokConfig
|
26
|
-
from django_cfg.models.tasks import TaskConfig
|
27
|
-
from django_cfg.modules.django_twilio.models import TwilioConfig
|
18
|
+
from django_cfg import (
|
19
|
+
ConfigurationError, ValidationError, EnvironmentError,
|
20
|
+
DatabaseConfig, CacheConfig, EmailConfig, TelegramConfig,
|
21
|
+
UnfoldConfig, DRFConfig, SpectacularConfig, LimitsConfig
|
22
|
+
)
|
28
23
|
|
29
24
|
# Default apps
|
30
25
|
DEFAULT_APPS = [
|
@@ -33,6 +28,7 @@ DEFAULT_APPS = [
|
|
33
28
|
"unfold.contrib.filters", # optional, if special filters are needed
|
34
29
|
"unfold.contrib.forms", # optional, if special form elements are needed
|
35
30
|
"unfold.contrib.inlines", # optional, if special inlines are needed
|
31
|
+
"import_export", # django-import-export package
|
36
32
|
"unfold.contrib.import_export", # optional, if django-import-export package is used
|
37
33
|
"unfold.contrib.guardian", # optional, if django-guardian package is used
|
38
34
|
"unfold.contrib.simple_history", # optional, if django-simple-history package is used
|
@@ -54,7 +50,6 @@ DEFAULT_APPS = [
|
|
54
50
|
"rest_framework_simplejwt.token_blacklist",
|
55
51
|
"rest_framework_nested",
|
56
52
|
"rangefilter",
|
57
|
-
"import_export",
|
58
53
|
"django_filters",
|
59
54
|
"drf_spectacular",
|
60
55
|
"drf_spectacular_sidecar",
|
@@ -62,6 +57,7 @@ DEFAULT_APPS = [
|
|
62
57
|
"django_extensions",
|
63
58
|
"constance",
|
64
59
|
"constance.backends.database",
|
60
|
+
"django_dramatiq",
|
65
61
|
# Django CFG
|
66
62
|
"django_cfg",
|
67
63
|
"django_revolution",
|
@@ -87,8 +83,8 @@ class DjangoConfig(BaseModel):
|
|
87
83
|
```python
|
88
84
|
class MyProjectConfig(DjangoConfig):
|
89
85
|
project_name: str = "My Project"
|
90
|
-
databases: Dict[str,
|
91
|
-
"default":
|
86
|
+
databases: Dict[str, DatabaseConfig] = {
|
87
|
+
"default": DatabaseConfig(
|
92
88
|
engine="django.db.backends.postgresql",
|
93
89
|
name="${DATABASE_URL:mydb}",
|
94
90
|
)
|
@@ -100,7 +96,7 @@ class DjangoConfig(BaseModel):
|
|
100
96
|
|
101
97
|
model_config = {
|
102
98
|
"validate_assignment": True,
|
103
|
-
"extra": "
|
99
|
+
"extra": "allow", # Allow additional fields for extensibility
|
104
100
|
"env_prefix": "DJANGO_",
|
105
101
|
"populate_by_name": True,
|
106
102
|
"validate_default": True,
|
@@ -149,6 +145,14 @@ class DjangoConfig(BaseModel):
|
|
149
145
|
default=False,
|
150
146
|
description="Enable django-cfg Leads application (lead collection, contact forms, CRM integration)",
|
151
147
|
)
|
148
|
+
enable_knowbase: bool = Field(
|
149
|
+
default=False,
|
150
|
+
description="Enable django-cfg Knowledge Base application (documents, AI chat, embeddings, search)",
|
151
|
+
)
|
152
|
+
enable_agents: bool = Field(
|
153
|
+
default=False,
|
154
|
+
description="Enable django-cfg AI Agents application (agent definitions, executions, workflows, tools)",
|
155
|
+
)
|
152
156
|
|
153
157
|
# === URLs ===
|
154
158
|
site_url: str = Field(default="http://localhost:3000", description="Frontend site URL")
|
@@ -196,18 +200,18 @@ class DjangoConfig(BaseModel):
|
|
196
200
|
)
|
197
201
|
|
198
202
|
# === Database Configuration ===
|
199
|
-
databases: Dict[str,
|
203
|
+
databases: Dict[str, DatabaseConfig] = Field(
|
200
204
|
default_factory=dict,
|
201
205
|
description="Database connections",
|
202
206
|
)
|
203
207
|
|
204
208
|
# === Cache Configuration ===
|
205
|
-
cache_default: Optional[
|
209
|
+
cache_default: Optional[CacheConfig] = Field(
|
206
210
|
default=None,
|
207
211
|
description="Default cache backend",
|
208
212
|
)
|
209
213
|
|
210
|
-
cache_sessions: Optional[
|
214
|
+
cache_sessions: Optional[CacheConfig] = Field(
|
211
215
|
default=None,
|
212
216
|
description="Sessions cache backend",
|
213
217
|
)
|
@@ -222,11 +226,6 @@ class DjangoConfig(BaseModel):
|
|
222
226
|
default=None,
|
223
227
|
description="Force SSL redirect on/off (None = auto based on domains and environment)",
|
224
228
|
)
|
225
|
-
|
226
|
-
cors_allow_headers: Optional[List[str]] = Field(
|
227
|
-
default=None,
|
228
|
-
description="Custom CORS allowed headers (None = use smart defaults including X-API-Key)",
|
229
|
-
)
|
230
229
|
|
231
230
|
# === Services Configuration ===
|
232
231
|
email: Optional[EmailConfig] = Field(
|
@@ -239,11 +238,6 @@ class DjangoConfig(BaseModel):
|
|
239
238
|
description="Telegram service configuration",
|
240
239
|
)
|
241
240
|
|
242
|
-
twilio: Optional[TwilioConfig] = Field(
|
243
|
-
default=None,
|
244
|
-
description="Twilio service configuration for OTP and messaging via WhatsApp, SMS, and Email",
|
245
|
-
)
|
246
|
-
|
247
241
|
# === Admin Interface Configuration ===
|
248
242
|
unfold: Optional[UnfoldConfig] = Field(
|
249
243
|
default=None,
|
@@ -267,18 +261,6 @@ class DjangoConfig(BaseModel):
|
|
267
261
|
description="Application limits configuration (file uploads, requests, etc.)",
|
268
262
|
)
|
269
263
|
|
270
|
-
# === Ngrok Configuration ===
|
271
|
-
ngrok: Optional[NgrokConfig] = Field(
|
272
|
-
default=None,
|
273
|
-
description="Ngrok tunnel configuration for development",
|
274
|
-
)
|
275
|
-
|
276
|
-
# === Task Processing Configuration ===
|
277
|
-
tasks: Optional[TaskConfig] = Field(
|
278
|
-
default=None,
|
279
|
-
description="Background task processing configuration with Dramatiq",
|
280
|
-
)
|
281
|
-
|
282
264
|
# === Middleware Configuration ===
|
283
265
|
custom_middleware: List[str] = Field(
|
284
266
|
default_factory=list,
|
@@ -551,11 +533,14 @@ class DjangoConfig(BaseModel):
|
|
551
533
|
apps.append("django_cfg.apps.newsletter")
|
552
534
|
if self.enable_leads:
|
553
535
|
apps.append("django_cfg.apps.leads")
|
554
|
-
|
555
|
-
|
556
|
-
if
|
557
|
-
|
558
|
-
|
536
|
+
if self.enable_knowbase:
|
537
|
+
apps.append("django_cfg.apps.knowbase")
|
538
|
+
if self.enable_agents:
|
539
|
+
apps.append("django_cfg.apps.agents")
|
540
|
+
|
541
|
+
# Auto-enable tasks if knowbase or agents are enabled
|
542
|
+
if self.enable_knowbase or self.enable_agents:
|
543
|
+
apps.append("django_cfg.apps.tasks")
|
559
544
|
|
560
545
|
# Auto-detect dashboard apps from Unfold callback
|
561
546
|
dashboard_apps = self._get_dashboard_apps_from_callback()
|
@@ -633,7 +618,6 @@ class DjangoConfig(BaseModel):
|
|
633
618
|
"django.contrib.sessions.middleware.SessionMiddleware",
|
634
619
|
"django.middleware.common.CommonMiddleware",
|
635
620
|
"django.middleware.csrf.CsrfViewMiddleware",
|
636
|
-
"django_cfg.middleware.PublicEndpointsMiddleware", # Handle invalid JWT tokens on public endpoints
|
637
621
|
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
638
622
|
"django.contrib.messages.middleware.MessageMiddleware",
|
639
623
|
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
@@ -710,43 +694,6 @@ class DjangoConfig(BaseModel):
|
|
710
694
|
return f"{self.site_url.rstrip('/')}/{path}"
|
711
695
|
return self.site_url
|
712
696
|
|
713
|
-
def get_ngrok_url(self, path: str = "") -> Optional[str]:
|
714
|
-
"""
|
715
|
-
Get the current ngrok tunnel URL with optional path.
|
716
|
-
|
717
|
-
This method retrieves the active ngrok URL from either:
|
718
|
-
1. The active ngrok manager instance
|
719
|
-
2. Environment variables set by runserver_ngrok command
|
720
|
-
|
721
|
-
Args:
|
722
|
-
path: Optional path to append to ngrok URL
|
723
|
-
|
724
|
-
Returns:
|
725
|
-
Complete ngrok URL with path, or None if ngrok is not available
|
726
|
-
|
727
|
-
Example:
|
728
|
-
config.get_ngrok_url("/api/webhooks/") # Returns: https://abc123.ngrok.io/api/webhooks/
|
729
|
-
"""
|
730
|
-
try:
|
731
|
-
# Import here to avoid circular imports
|
732
|
-
from django_cfg.modules.django_ngrok import get_effective_tunnel_url
|
733
|
-
|
734
|
-
tunnel_url = get_effective_tunnel_url()
|
735
|
-
if not tunnel_url:
|
736
|
-
return None
|
737
|
-
|
738
|
-
if path:
|
739
|
-
path = path.lstrip("/")
|
740
|
-
return f"{tunnel_url.rstrip('/')}/{path}"
|
741
|
-
return tunnel_url
|
742
|
-
|
743
|
-
except ImportError:
|
744
|
-
# django_ngrok module not available
|
745
|
-
return None
|
746
|
-
except Exception:
|
747
|
-
# Any other error - fail silently
|
748
|
-
return None
|
749
|
-
|
750
697
|
def invalidate_cache(self) -> None:
|
751
698
|
"""Invalidate cached Django settings to force regeneration."""
|
752
699
|
self._django_settings = None
|
django_cfg/core/environment.py
CHANGED
django_cfg/core/generation.py
CHANGED
@@ -12,7 +12,7 @@ from typing import Dict, List, Any, TYPE_CHECKING
|
|
12
12
|
from pathlib import Path
|
13
13
|
import logging
|
14
14
|
|
15
|
-
from django_cfg.exceptions import ConfigurationError
|
15
|
+
from django_cfg.core.exceptions import ConfigurationError
|
16
16
|
from django_cfg.utils.smart_defaults import SmartDefaults
|
17
17
|
|
18
18
|
if TYPE_CHECKING:
|
@@ -76,20 +76,6 @@ class SettingsGenerator:
|
|
76
76
|
# Generate third-party integration settings
|
77
77
|
settings.update(cls._generate_integration_settings(config))
|
78
78
|
|
79
|
-
# Generate task processing settings
|
80
|
-
task_settings = cls._generate_task_settings(config)
|
81
|
-
settings.update(task_settings)
|
82
|
-
|
83
|
-
# Merge task apps into INSTALLED_APPS if they exist
|
84
|
-
if "_TASK_APPS" in task_settings:
|
85
|
-
task_apps = task_settings["_TASK_APPS"]
|
86
|
-
if "INSTALLED_APPS" in settings and task_apps:
|
87
|
-
for app in task_apps:
|
88
|
-
if app not in settings["INSTALLED_APPS"]:
|
89
|
-
settings["INSTALLED_APPS"].append(app)
|
90
|
-
# Remove the temporary key
|
91
|
-
settings.pop("_TASK_APPS", None)
|
92
|
-
|
93
79
|
return settings
|
94
80
|
|
95
81
|
except Exception as e:
|
@@ -195,7 +181,7 @@ class SettingsGenerator:
|
|
195
181
|
routing_rules[app] = alias
|
196
182
|
|
197
183
|
if routing_rules:
|
198
|
-
settings["DATABASE_ROUTERS"] = ["django_cfg.routers.DatabaseRouter"]
|
184
|
+
settings["DATABASE_ROUTERS"] = ["django_cfg.routing.routers.DatabaseRouter"]
|
199
185
|
settings["DATABASE_ROUTING_RULES"] = routing_rules
|
200
186
|
|
201
187
|
return settings
|
@@ -214,12 +200,11 @@ class SettingsGenerator:
|
|
214
200
|
if config.cache_default:
|
215
201
|
caches["default"] = config.cache_default.to_django_config(config._environment, config.debug, "default")
|
216
202
|
else:
|
217
|
-
#
|
218
|
-
|
203
|
+
# Create default cache backend
|
204
|
+
from django_cfg.models.cache import CacheConfig
|
219
205
|
|
220
|
-
|
221
|
-
|
222
|
-
pass
|
206
|
+
default_cache = CacheConfig()
|
207
|
+
caches["default"] = default_cache.to_django_config(config._environment, config.debug, "default")
|
223
208
|
|
224
209
|
# Sessions cache
|
225
210
|
if config.cache_sessions:
|
@@ -257,8 +242,7 @@ class SettingsGenerator:
|
|
257
242
|
config.security_domains,
|
258
243
|
config._environment,
|
259
244
|
config.debug,
|
260
|
-
config.ssl_redirect
|
261
|
-
config.cors_allow_headers
|
245
|
+
config.ssl_redirect
|
262
246
|
)
|
263
247
|
settings.update(security_defaults)
|
264
248
|
|
@@ -420,15 +404,6 @@ class SettingsGenerator:
|
|
420
404
|
|
421
405
|
# Check for Constance configuration
|
422
406
|
if hasattr(config, "constance") and config.constance:
|
423
|
-
try:
|
424
|
-
if hasattr(config, "tasks") and config.tasks and config.tasks.enabled:
|
425
|
-
from django_cfg.modules.django_tasks import extend_constance_config_with_tasks
|
426
|
-
task_fields = extend_constance_config_with_tasks()
|
427
|
-
if task_fields:
|
428
|
-
config.constance.fields.extend(task_fields)
|
429
|
-
except Exception as e:
|
430
|
-
logger.warning(f"Failed to extend Constance with task fields: {e}")
|
431
|
-
|
432
407
|
constance_settings = config.constance.to_django_settings()
|
433
408
|
settings.update(constance_settings)
|
434
409
|
integrations.append("constance")
|
@@ -439,6 +414,18 @@ class SettingsGenerator:
|
|
439
414
|
settings.update(jwt_settings)
|
440
415
|
integrations.append("jwt")
|
441
416
|
|
417
|
+
# Check for Tasks/Dramatiq configuration
|
418
|
+
try:
|
419
|
+
from django_cfg.modules.django_tasks import generate_dramatiq_settings_from_config
|
420
|
+
dramatiq_settings = generate_dramatiq_settings_from_config(config)
|
421
|
+
if dramatiq_settings:
|
422
|
+
settings.update(dramatiq_settings)
|
423
|
+
integrations.append("dramatiq")
|
424
|
+
except ImportError as e:
|
425
|
+
logger.warning(f"Failed to import django_tasks module: {e}")
|
426
|
+
except Exception as e:
|
427
|
+
logger.error(f"Failed to generate Dramatiq settings: {e}")
|
428
|
+
|
442
429
|
# Check for Django Revolution configuration
|
443
430
|
if hasattr(config, "revolution") and config.revolution:
|
444
431
|
revolution_settings = {
|
@@ -542,81 +529,6 @@ class SettingsGenerator:
|
|
542
529
|
|
543
530
|
return errors
|
544
531
|
|
545
|
-
@classmethod
|
546
|
-
def _generate_task_settings(cls, config: "DjangoConfig") -> Dict[str, Any]:
|
547
|
-
"""
|
548
|
-
Generate task processing settings for Dramatiq integration.
|
549
|
-
|
550
|
-
Args:
|
551
|
-
config: DjangoConfig instance
|
552
|
-
|
553
|
-
Returns:
|
554
|
-
Task processing settings dictionary
|
555
|
-
"""
|
556
|
-
if not config.tasks or not config.tasks.enabled:
|
557
|
-
return {}
|
558
|
-
|
559
|
-
settings = {}
|
560
|
-
|
561
|
-
try:
|
562
|
-
# Check if Dramatiq dependencies are available
|
563
|
-
import dramatiq
|
564
|
-
import django_dramatiq
|
565
|
-
|
566
|
-
# Generate task apps directly without using task service to avoid circular dependency
|
567
|
-
task_apps = ["django_dramatiq"]
|
568
|
-
|
569
|
-
# Add custom tasks app if admin is enabled
|
570
|
-
if config.tasks.dramatiq and config.tasks.dramatiq.admin_enabled:
|
571
|
-
task_apps.append("django_cfg.apps.tasks")
|
572
|
-
|
573
|
-
settings["_TASK_APPS"] = task_apps
|
574
|
-
|
575
|
-
# Generate minimal Dramatiq broker settings
|
576
|
-
if (config.cache_default and
|
577
|
-
config.cache_default.redis_url and
|
578
|
-
config.tasks.dramatiq):
|
579
|
-
|
580
|
-
redis_db = config.tasks.dramatiq.redis_db or 0
|
581
|
-
redis_url = config.cache_default.redis_url
|
582
|
-
|
583
|
-
# Fix Redis URL to use correct database
|
584
|
-
from urllib.parse import urlparse, urlunparse
|
585
|
-
parsed = urlparse(redis_url)
|
586
|
-
# Replace the path (database) with the correct one
|
587
|
-
fixed_url = urlunparse((
|
588
|
-
parsed.scheme,
|
589
|
-
parsed.netloc,
|
590
|
-
f"/{redis_db}",
|
591
|
-
parsed.params,
|
592
|
-
parsed.query,
|
593
|
-
parsed.fragment
|
594
|
-
))
|
595
|
-
|
596
|
-
settings["DRAMATIQ_BROKER"] = {
|
597
|
-
"BROKER": "dramatiq.brokers.redis.RedisBroker",
|
598
|
-
"OPTIONS": {
|
599
|
-
"url": fixed_url,
|
600
|
-
},
|
601
|
-
"MIDDLEWARE": [
|
602
|
-
"dramatiq.middleware.AgeLimit",
|
603
|
-
"dramatiq.middleware.TimeLimit",
|
604
|
-
"dramatiq.middleware.Callbacks",
|
605
|
-
"dramatiq.middleware.Retries",
|
606
|
-
"django_dramatiq.middleware.AdminMiddleware",
|
607
|
-
"django_dramatiq.middleware.DbConnectionsMiddleware",
|
608
|
-
]
|
609
|
-
}
|
610
|
-
|
611
|
-
logger.debug(f"Generated task settings with {len(task_apps)} apps")
|
612
|
-
|
613
|
-
except ImportError:
|
614
|
-
logger.warning("Dramatiq dependencies not available, skipping task settings")
|
615
|
-
except Exception as e:
|
616
|
-
logger.error(f"Failed to generate task settings: {e}")
|
617
|
-
|
618
|
-
return settings
|
619
|
-
|
620
532
|
|
621
533
|
# Export the main class
|
622
534
|
__all__ = [
|
@@ -89,25 +89,27 @@ def get_django_cfg_urls_info() -> dict:
|
|
89
89
|
]
|
90
90
|
|
91
91
|
try:
|
92
|
-
from django_cfg.modules.base import
|
93
|
-
base_module =
|
92
|
+
from django_cfg.modules.base import BaseCfgModule
|
93
|
+
base_module = BaseCfgModule()
|
94
94
|
|
95
|
-
#
|
96
|
-
if base_module.is_support_enabled():
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
if base_module.is_leads_enabled():
|
106
|
-
endpoints.append("cfg/leads/")
|
107
|
-
|
95
|
+
# All business logic apps are handled by Django Revolution zones
|
96
|
+
# if base_module.is_support_enabled():
|
97
|
+
# endpoints.append("cfg/support/")
|
98
|
+
# if base_module.is_accounts_enabled():
|
99
|
+
# endpoints.append("cfg/accounts/")
|
100
|
+
# Newsletter and Leads are handled by Django Revolution zones
|
101
|
+
# if base_module.is_newsletter_enabled():
|
102
|
+
# endpoints.append("cfg/newsletter/")
|
103
|
+
# if base_module.is_leads_enabled():
|
104
|
+
# endpoints.append("cfg/leads/")
|
108
105
|
except Exception:
|
109
106
|
# Fallback: show all possible endpoints
|
110
|
-
|
107
|
+
endpoints.extend([
|
108
|
+
"cfg/support/",
|
109
|
+
"cfg/accounts/",
|
110
|
+
"cfg/newsletter/",
|
111
|
+
"cfg/leads/",
|
112
|
+
])
|
111
113
|
|
112
114
|
info = {
|
113
115
|
"django_cfg": {
|
django_cfg/core/validation.py
CHANGED
@@ -12,7 +12,7 @@ from typing import List, Dict, Any, Optional, Set, Tuple, TYPE_CHECKING
|
|
12
12
|
import re
|
13
13
|
from pathlib import Path
|
14
14
|
|
15
|
-
from django_cfg.exceptions import ValidationError, ConfigurationError
|
15
|
+
from django_cfg.core.exceptions import ValidationError, ConfigurationError
|
16
16
|
|
17
17
|
if TYPE_CHECKING:
|
18
18
|
from django_cfg.core.config import DjangoConfig
|
@@ -1 +1 @@
|
|
1
|
-
# Django management
|
1
|
+
# Django management package
|
@@ -1 +1 @@
|
|
1
|
-
# Django management commands
|
1
|
+
# Django management commands
|