django-cfg 1.3.11__py3-none-any.whl → 1.4.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 +1 -1
- django_cfg/apps/accounts/admin/inlines.py +11 -5
- django_cfg/apps/accounts/admin/user_admin.py +39 -16
- django_cfg/apps/accounts/serializers/profile.py +1 -1
- django_cfg/apps/accounts/services/otp_service.py +18 -11
- django_cfg/apps/accounts/signals.py +15 -24
- django_cfg/apps/accounts/utils/notifications.py +217 -358
- django_cfg/apps/accounts/views/otp.py +2 -2
- django_cfg/apps/accounts/views/webhook.py +1 -1
- django_cfg/apps/agents/core/django_agent.py +1 -1
- django_cfg/apps/api/commands/views.py +66 -83
- django_cfg/apps/api/health/drf_views.py +269 -0
- django_cfg/apps/api/health/serializers.py +45 -0
- django_cfg/apps/api/health/urls.py +6 -1
- django_cfg/apps/knowbase/admin/actions/__init__.py +13 -0
- django_cfg/apps/knowbase/admin/actions/visibility_actions.py +56 -0
- django_cfg/apps/knowbase/admin/document_admin.py +136 -270
- django_cfg/apps/knowbase/admin/helpers/__init__.py +17 -0
- django_cfg/apps/knowbase/admin/helpers/configs.py +72 -0
- django_cfg/apps/knowbase/admin/helpers/display_helpers.py +156 -0
- django_cfg/apps/knowbase/admin/helpers/statistics.py +108 -0
- django_cfg/apps/knowbase/config/constance_fields.py +1 -1
- django_cfg/apps/knowbase/config/settings.py +2 -2
- django_cfg/apps/knowbase/mixins/__init__.py +19 -2
- django_cfg/apps/knowbase/mixins/config/__init__.py +14 -0
- django_cfg/apps/knowbase/mixins/config/defaults.py +75 -0
- django_cfg/apps/knowbase/mixins/config/meta_config.py +120 -0
- django_cfg/apps/knowbase/mixins/creator.py +10 -10
- django_cfg/apps/knowbase/mixins/external_data_mixin.py +105 -403
- django_cfg/apps/knowbase/mixins/generators/__init__.py +16 -0
- django_cfg/apps/knowbase/mixins/generators/content_generator.py +218 -0
- django_cfg/apps/knowbase/mixins/generators/field_analyzer.py +76 -0
- django_cfg/apps/knowbase/mixins/generators/metadata_generator.py +124 -0
- django_cfg/apps/knowbase/mixins/service.py +2 -2
- django_cfg/apps/knowbase/services/archive/__init__.py +1 -0
- django_cfg/apps/knowbase/services/archive/analyzers/__init__.py +17 -0
- django_cfg/apps/knowbase/services/archive/analyzers/complexity_analyzer.py +33 -0
- django_cfg/apps/knowbase/services/archive/analyzers/purpose_detector.py +36 -0
- django_cfg/apps/knowbase/services/archive/analyzers/quality_analyzer.py +39 -0
- django_cfg/apps/knowbase/services/archive/analyzers/tag_generator.py +103 -0
- django_cfg/apps/knowbase/services/archive/chunking/__init__.py +19 -0
- django_cfg/apps/knowbase/services/archive/chunking/base.py +81 -0
- django_cfg/apps/knowbase/services/archive/chunking/json_chunker.py +62 -0
- django_cfg/apps/knowbase/services/archive/chunking/markdown_chunker.py +107 -0
- django_cfg/apps/knowbase/services/archive/chunking/python_chunker.py +248 -0
- django_cfg/apps/knowbase/services/archive/chunking/text_chunker.py +70 -0
- django_cfg/apps/knowbase/services/archive/chunking_service.py +110 -729
- django_cfg/apps/knowbase/services/archive/context/__init__.py +14 -0
- django_cfg/apps/knowbase/services/archive/context/builders.py +220 -0
- django_cfg/apps/knowbase/services/archive/context/models.py +38 -0
- django_cfg/apps/knowbase/services/embedding/models.py +18 -14
- django_cfg/apps/knowbase/services/embedding/processors.py +6 -3
- django_cfg/apps/knowbase/tasks/document_processing.py +11 -3
- django_cfg/apps/leads/tests.py +1 -1
- django_cfg/apps/payments/admin/api_keys_admin.py +1 -1
- django_cfg/apps/payments/admin/balance_admin.py +1 -1
- django_cfg/apps/payments/admin/currencies_admin.py +1 -1
- django_cfg/apps/payments/admin/payments_admin.py +1 -1
- django_cfg/apps/payments/admin/subscriptions_admin.py +1 -1
- django_cfg/apps/payments/admin_interface/templates/payments/base.html +59 -126
- django_cfg/apps/payments/admin_interface/views/api/payments.py +1 -1
- django_cfg/apps/payments/admin_interface/views/api/stats.py +1 -1
- django_cfg/apps/payments/admin_interface/views/api/users.py +1 -1
- django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +1 -1
- django_cfg/apps/payments/admin_interface/views/api/webhook_public.py +1 -1
- django_cfg/apps/payments/admin_interface/views/base.py +29 -2
- django_cfg/apps/payments/apps.py +1 -1
- django_cfg/apps/payments/config/django_cfg_integration.py +2 -2
- django_cfg/apps/payments/config/helpers.py +3 -2
- django_cfg/apps/payments/management/commands/cleanup_expired_data.py +1 -1
- django_cfg/apps/payments/management/commands/currency_stats.py +1 -1
- django_cfg/apps/payments/management/commands/manage_currencies.py +1 -1
- django_cfg/apps/payments/management/commands/manage_providers.py +1 -1
- django_cfg/apps/payments/management/commands/process_pending_payments.py +1 -1
- django_cfg/apps/payments/management/commands/test_providers.py +1 -1
- django_cfg/apps/payments/middleware/api_access.py +1 -1
- django_cfg/apps/payments/middleware/rate_limiting.py +1 -1
- django_cfg/apps/payments/middleware/usage_tracking.py +1 -1
- django_cfg/apps/payments/models/balance.py +2 -2
- django_cfg/apps/payments/models/managers/api_key_managers.py +1 -1
- django_cfg/apps/payments/models/managers/balance_managers.py +1 -1
- django_cfg/apps/payments/models/managers/currency_managers.py +1 -1
- django_cfg/apps/payments/models/managers/payment_managers.py +1 -1
- django_cfg/apps/payments/models/managers/subscription_managers.py +1 -1
- django_cfg/apps/payments/models/payments.py +2 -2
- django_cfg/apps/payments/services/cache_service/__init__.py +1 -1
- django_cfg/apps/payments/services/cache_service/simple_cache.py +10 -5
- django_cfg/apps/payments/services/core/base.py +1 -1
- django_cfg/apps/payments/services/core/currency/__init__.py +13 -0
- django_cfg/apps/payments/services/core/currency/currency_converter.py +57 -0
- django_cfg/apps/payments/services/core/currency/currency_validator.py +61 -0
- django_cfg/apps/payments/services/core/operations/__init__.py +15 -0
- django_cfg/apps/payments/services/core/operations/payment_canceller.py +100 -0
- django_cfg/apps/payments/services/core/operations/payment_creator.py +196 -0
- django_cfg/apps/payments/services/core/operations/status_checker.py +100 -0
- django_cfg/apps/payments/services/core/payment_service.py +124 -612
- django_cfg/apps/payments/services/core/providers/__init__.py +13 -0
- django_cfg/apps/payments/services/core/providers/provider_client.py +132 -0
- django_cfg/apps/payments/services/core/providers/status_mapper.py +89 -0
- django_cfg/apps/payments/services/core/utils/__init__.py +13 -0
- django_cfg/apps/payments/services/core/utils/data_converter.py +48 -0
- django_cfg/apps/payments/services/core/utils/statistics_calculator.py +69 -0
- django_cfg/apps/payments/services/providers/base.py +1 -1
- django_cfg/apps/payments/services/providers/nowpayments/__init__.py +3 -3
- django_cfg/apps/payments/services/providers/nowpayments/parsers/__init__.py +9 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/__init__.py +23 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/constants.py +23 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/currency_names.py +244 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/patterns.py +511 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/parser.py +168 -0
- django_cfg/apps/payments/services/providers/nowpayments/provider.py +1 -1
- django_cfg/apps/payments/services/providers/nowpayments/sync.py +1 -1
- django_cfg/apps/payments/services/providers/registry.py +1 -1
- django_cfg/apps/payments/services/providers/sync_service.py +1 -1
- django_cfg/apps/payments/signals/__init__.py +1 -1
- django_cfg/apps/payments/signals/api_key_signals.py +1 -1
- django_cfg/apps/payments/signals/balance_signals.py +1 -1
- django_cfg/apps/payments/signals/payment_signals.py +1 -1
- django_cfg/apps/payments/signals/subscription_signals.py +1 -1
- django_cfg/apps/payments/views/api/api_keys.py +1 -1
- django_cfg/apps/payments/views/api/balances.py +1 -1
- django_cfg/apps/payments/views/api/base.py +1 -1
- django_cfg/apps/payments/views/api/currencies.py +1 -1
- django_cfg/apps/payments/views/api/payments.py +1 -1
- django_cfg/apps/payments/views/api/subscriptions.py +1 -1
- django_cfg/apps/payments/views/api/webhooks.py +1 -1
- django_cfg/apps/payments/views/serializers/api_keys.py +1 -1
- django_cfg/apps/payments/views/serializers/balances.py +1 -1
- django_cfg/apps/payments/views/serializers/currencies.py +1 -1
- django_cfg/apps/payments/views/serializers/payments.py +1 -1
- django_cfg/apps/payments/views/serializers/subscriptions.py +1 -1
- django_cfg/apps/payments/views/serializers/webhooks.py +1 -1
- django_cfg/apps/support/admin/support_admin.py +21 -13
- django_cfg/apps/support/templates/support/chat/access_denied.html +21 -27
- django_cfg/apps/support/templates/support/chat/ticket_chat.html +183 -254
- django_cfg/apps/support/utils/support_email_service.py +1 -1
- django_cfg/apps/tasks/templates/tasks/layout/base.html +20 -115
- django_cfg/apps/tasks/utils/simulator.py +1 -1
- django_cfg/apps/tasks/views/dashboard.py +33 -3
- django_cfg/apps/urls.py +5 -1
- django_cfg/cli/README.md +57 -471
- django_cfg/cli/commands/create_project.py +140 -529
- django_cfg/cli/main.py +13 -10
- django_cfg/core/__init__.py +63 -6
- django_cfg/core/base/__init__.py +5 -0
- django_cfg/core/base/config_model.py +652 -0
- django_cfg/core/builders/__init__.py +11 -0
- django_cfg/core/builders/apps_builder.py +258 -0
- django_cfg/core/builders/middleware_builder.py +115 -0
- django_cfg/core/builders/security_builder.py +96 -0
- django_cfg/core/config.py +20 -892
- django_cfg/core/constants.py +69 -0
- django_cfg/core/environment/__init__.py +9 -0
- django_cfg/core/exceptions.py +45 -298
- django_cfg/core/generation/__init__.py +51 -0
- django_cfg/core/generation/core_generators/__init__.py +0 -0
- django_cfg/core/generation/core_generators/settings.py +90 -0
- django_cfg/core/generation/core_generators/static.py +82 -0
- django_cfg/core/generation/core_generators/templates.py +141 -0
- django_cfg/core/generation/data_generators/__init__.py +15 -0
- django_cfg/core/generation/data_generators/cache.py +132 -0
- django_cfg/core/generation/data_generators/database.py +117 -0
- django_cfg/core/generation/generation.py +92 -0
- django_cfg/core/generation/integration_generators/__init__.py +21 -0
- django_cfg/core/generation/integration_generators/api.py +237 -0
- django_cfg/core/generation/integration_generators/sessions.py +65 -0
- django_cfg/core/generation/integration_generators/tailwind.py +54 -0
- django_cfg/core/generation/integration_generators/tasks.py +92 -0
- django_cfg/core/generation/integration_generators/third_party.py +144 -0
- django_cfg/core/generation/orchestrator.py +285 -0
- django_cfg/core/generation/protocols.py +30 -0
- django_cfg/core/generation/security_generators/__init__.py +0 -0
- django_cfg/core/generation/utility_generators/__init__.py +24 -0
- django_cfg/core/generation/utility_generators/email.py +58 -0
- django_cfg/core/generation/utility_generators/i18n.py +66 -0
- django_cfg/core/generation/utility_generators/limits.py +58 -0
- django_cfg/core/generation/utility_generators/logging.py +66 -0
- django_cfg/core/generation/utility_generators/security.py +101 -0
- django_cfg/core/generation/utils/__init__.py +0 -0
- django_cfg/core/generation/utils/helpers.py +32 -0
- django_cfg/core/integration/__init__.py +18 -25
- django_cfg/core/integration/display/startup.py +146 -133
- django_cfg/core/integration/url_integration.py +13 -2
- django_cfg/core/services/__init__.py +5 -0
- django_cfg/core/services/config_service.py +121 -0
- django_cfg/core/state/__init__.py +9 -0
- django_cfg/core/state/registry.py +84 -0
- django_cfg/core/types/__init__.py +15 -0
- django_cfg/core/types/aliases.py +15 -0
- django_cfg/core/types/enums.py +49 -0
- django_cfg/dashboard/DEBUG_README.md +105 -0
- django_cfg/dashboard/REFACTORING_SUMMARY.md +237 -0
- django_cfg/dashboard/__init__.py +24 -0
- django_cfg/dashboard/components.py +308 -0
- django_cfg/dashboard/debug.py +176 -0
- django_cfg/dashboard/management/__init__.py +0 -0
- django_cfg/dashboard/management/commands/__init__.py +0 -0
- django_cfg/dashboard/management/commands/debug_dashboard.py +109 -0
- django_cfg/dashboard/sections/__init__.py +1 -0
- django_cfg/dashboard/sections/base.py +128 -0
- django_cfg/dashboard/sections/commands.py +32 -0
- django_cfg/dashboard/sections/overview.py +394 -0
- django_cfg/dashboard/sections/stats.py +48 -0
- django_cfg/dashboard/sections/system.py +73 -0
- django_cfg/management/commands/check_settings.py +6 -2
- django_cfg/management/commands/clear_constance.py +6 -1
- django_cfg/management/commands/create_token.py +5 -4
- django_cfg/management/commands/generate.py +5 -0
- django_cfg/management/commands/list_urls.py +7 -2
- django_cfg/management/commands/migrate_all.py +6 -2
- django_cfg/management/commands/migrator.py +6 -1
- django_cfg/management/commands/rundramatiq.py +6 -1
- django_cfg/management/commands/rundramatiq_simulator.py +11 -4
- django_cfg/management/commands/runserver_ngrok.py +9 -7
- django_cfg/management/commands/script.py +25 -21
- django_cfg/management/commands/show_config.py +6 -1
- django_cfg/management/commands/show_urls.py +8 -3
- django_cfg/management/commands/superuser.py +5 -4
- django_cfg/management/commands/task_clear.py +8 -3
- django_cfg/management/commands/task_status.py +8 -3
- django_cfg/management/commands/test_email.py +6 -1
- django_cfg/management/commands/test_telegram.py +6 -1
- django_cfg/management/commands/test_twilio.py +6 -1
- django_cfg/management/commands/tree.py +7 -4
- django_cfg/models/__init__.py +88 -3
- django_cfg/models/api/__init__.py +27 -0
- django_cfg/models/{api.py → api/config.py} +1 -1
- django_cfg/models/api/drf/__init__.py +21 -0
- django_cfg/models/api/drf/config.py +101 -0
- django_cfg/models/api/drf/redoc.py +31 -0
- django_cfg/models/api/drf/spectacular.py +129 -0
- django_cfg/models/api/drf/swagger.py +59 -0
- django_cfg/models/{api_keys.py → api/keys.py} +16 -6
- django_cfg/models/{limits.py → api/limits.py} +0 -1
- django_cfg/models/base/__init__.py +14 -0
- django_cfg/models/django/__init__.py +16 -0
- django_cfg/models/{constance.py → django/constance.py} +1 -1
- django_cfg/models/{environment.py → django/environment.py} +1 -1
- django_cfg/models/infrastructure/__init__.py +17 -0
- django_cfg/models/{cache.py → infrastructure/cache.py} +3 -2
- django_cfg/models/infrastructure/database/__init__.py +22 -0
- django_cfg/models/infrastructure/database/config.py +265 -0
- django_cfg/models/infrastructure/database/converters.py +91 -0
- django_cfg/models/infrastructure/database/parsers.py +96 -0
- django_cfg/models/infrastructure/database/routing.py +85 -0
- django_cfg/models/infrastructure/database/validators.py +170 -0
- django_cfg/models/{logging.py → infrastructure/logging.py} +1 -1
- django_cfg/models/{security.py → infrastructure/security.py} +2 -2
- django_cfg/models/ngrok/__init__.py +11 -0
- django_cfg/models/ngrok/auth.py +37 -0
- django_cfg/models/ngrok/config.py +77 -0
- django_cfg/models/ngrok/tunnel.py +35 -0
- django_cfg/models/payments/__init__.py +20 -0
- django_cfg/models/payments/api_keys.py +57 -0
- django_cfg/models/{payments.py → payments/config.py} +56 -154
- django_cfg/models/payments/providers/__init__.py +15 -0
- django_cfg/models/payments/providers/base.py +25 -0
- django_cfg/models/payments/providers/nowpayments.py +48 -0
- django_cfg/models/services/__init__.py +18 -0
- django_cfg/models/services/base.py +65 -0
- django_cfg/models/{email.py → services/email.py} +1 -1
- django_cfg/models/services/telegram.py +172 -0
- django_cfg/models/tasks/__init__.py +51 -0
- django_cfg/models/tasks/backends.py +250 -0
- django_cfg/models/tasks/config.py +314 -0
- django_cfg/models/tasks/utils.py +174 -0
- django_cfg/modules/base.py +18 -3
- django_cfg/modules/django_admin/decorators/actions.py +1 -1
- django_cfg/modules/django_admin/decorators/display.py +1 -1
- django_cfg/modules/django_admin/mixins/standalone_actions_mixin.py +1 -1
- django_cfg/modules/django_cfg_rpc_client/README.md +346 -0
- django_cfg/modules/django_cfg_rpc_client/__init__.py +51 -0
- django_cfg/modules/django_cfg_rpc_client/client.py +540 -0
- django_cfg/modules/django_cfg_rpc_client/config.py +207 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/README.md +517 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/UNFOLD_INTEGRATION.md +439 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/__init__.py +11 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/apps.py +22 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/monitor.py +435 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/static/django_cfg_rpc_dashboard/js/dashboard.js +373 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/templates/django_cfg_rpc_dashboard/base.html +76 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/templates/django_cfg_rpc_dashboard/dashboard.html +200 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/urls.py +22 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/urls_admin.py +9 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/views.py +251 -0
- django_cfg/modules/django_cfg_rpc_client/exceptions.py +201 -0
- django_cfg/modules/django_drf_theme/CHANGELOG.md +210 -0
- django_cfg/modules/django_drf_theme/EXAMPLE.md +465 -0
- django_cfg/modules/django_drf_theme/IMPLEMENTATION.md +232 -0
- django_cfg/modules/django_drf_theme/README.md +207 -0
- django_cfg/modules/django_drf_theme/TAILWIND_CDN_GUIDE.md +274 -0
- django_cfg/modules/django_drf_theme/__init__.py +23 -0
- django_cfg/modules/django_drf_theme/apps.py +15 -0
- django_cfg/modules/django_drf_theme/renderers.py +58 -0
- django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/api.html +375 -0
- django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/base.html +938 -0
- django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/forms/filter_form.html +132 -0
- django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/forms/raw_data_form.html +123 -0
- django_cfg/modules/django_drf_theme/templatetags/__init__.py +1 -0
- django_cfg/modules/django_drf_theme/templatetags/tailwind_tags.py +57 -0
- django_cfg/modules/django_email/__init__.py +14 -0
- django_cfg/modules/{django_email.py → django_email/service.py} +78 -113
- django_cfg/modules/django_email/utils.py +40 -0
- django_cfg/modules/django_health/__init__.py +9 -0
- django_cfg/modules/{django_health.py → django_health/service.py} +23 -21
- django_cfg/modules/django_llm/llm/client.py +155 -550
- django_cfg/modules/django_llm/llm/embeddings/__init__.py +13 -0
- django_cfg/modules/django_llm/llm/embeddings/mock_embedder.py +106 -0
- django_cfg/modules/django_llm/llm/embeddings/openai_embedder.py +79 -0
- django_cfg/modules/django_llm/llm/models_api/__init__.py +9 -0
- django_cfg/modules/django_llm/llm/models_api/models_query.py +163 -0
- django_cfg/modules/django_llm/llm/providers/__init__.py +15 -0
- django_cfg/modules/django_llm/llm/providers/config_builder.py +103 -0
- django_cfg/modules/django_llm/llm/providers/provider_manager.py +148 -0
- django_cfg/modules/django_llm/llm/providers/provider_selector.py +60 -0
- django_cfg/modules/django_llm/llm/requests/__init__.py +15 -0
- django_cfg/modules/django_llm/llm/requests/cache_manager.py +170 -0
- django_cfg/modules/django_llm/llm/requests/chat_handler.py +199 -0
- django_cfg/modules/django_llm/llm/requests/embedding_handler.py +113 -0
- django_cfg/modules/django_llm/llm/responses/__init__.py +9 -0
- django_cfg/modules/django_llm/llm/responses/response_builder.py +131 -0
- django_cfg/modules/django_llm/llm/stats/__init__.py +9 -0
- django_cfg/modules/django_llm/llm/stats/stats_manager.py +107 -0
- django_cfg/modules/django_llm/translator/detectors/__init__.py +13 -0
- django_cfg/modules/django_llm/translator/detectors/language_detector.py +90 -0
- django_cfg/modules/django_llm/translator/detectors/script_detector.py +153 -0
- django_cfg/modules/django_llm/translator/stats/__init__.py +11 -0
- django_cfg/modules/django_llm/translator/stats/stats_tracker.py +85 -0
- django_cfg/modules/django_llm/translator/translator.py +150 -603
- django_cfg/modules/django_llm/translator/translators/__init__.py +15 -0
- django_cfg/modules/django_llm/translator/translators/json_translator.py +316 -0
- django_cfg/modules/django_llm/translator/translators/text_translator.py +139 -0
- django_cfg/modules/django_llm/translator/utils/__init__.py +13 -0
- django_cfg/modules/django_llm/translator/utils/prompt_builder.py +110 -0
- django_cfg/modules/django_llm/translator/utils/text_utils.py +114 -0
- django_cfg/modules/django_logging/FIXES_SUMMARY.md +276 -0
- django_cfg/modules/django_logging/LOGGING_GUIDE.md +504 -0
- django_cfg/modules/django_logging/__init__.py +14 -0
- django_cfg/modules/{django_logger.py → django_logging/django_logger.py} +13 -13
- django_cfg/modules/{logger.py → django_logging/logger.py} +14 -4
- django_cfg/modules/django_ngrok/__init__.py +39 -0
- django_cfg/modules/{django_ngrok.py → django_ngrok/service.py} +14 -42
- django_cfg/modules/django_rpc_old/POETRY.md +344 -0
- django_cfg/modules/django_rpc_old/README.md +397 -0
- django_cfg/modules/django_rpc_old/TESTING.md +358 -0
- django_cfg/modules/django_rpc_old/__init__.py +39 -0
- django_cfg/modules/django_rpc_old/client.py +531 -0
- django_cfg/modules/django_rpc_old/config.py +279 -0
- django_cfg/modules/django_rpc_old/exceptions.py +172 -0
- django_cfg/modules/django_tailwind/README.md +478 -0
- django_cfg/modules/django_tailwind/__init__.py +7 -0
- django_cfg/modules/django_tailwind/apps.py +10 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/app.html +5 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/base.html +117 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/components/navbar.html +124 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/components/theme_toggle.html +54 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/components/user_menu.html +116 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/simple.html +46 -0
- django_cfg/modules/django_tailwind/templatetags/__init__.py +1 -0
- django_cfg/modules/django_tailwind/templatetags/tailwind_info.py +185 -0
- django_cfg/modules/django_tasks/__init__.py +29 -0
- django_cfg/modules/django_tasks/factory.py +127 -0
- django_cfg/modules/{django_tasks.py → django_tasks/service.py} +45 -274
- django_cfg/modules/django_tasks/settings.py +107 -0
- django_cfg/modules/django_telegram/__init__.py +29 -0
- django_cfg/modules/{django_telegram.py → django_telegram/service.py} +45 -113
- django_cfg/modules/django_telegram/utils.py +62 -0
- django_cfg/modules/django_twilio/__init__.py +54 -107
- django_cfg/modules/django_twilio/_imports.py +30 -0
- django_cfg/modules/django_twilio/base.py +192 -0
- django_cfg/modules/django_twilio/email_otp.py +227 -0
- django_cfg/modules/django_twilio/sendgrid_service.py +1 -1
- django_cfg/modules/django_twilio/simple_service.py +1 -2
- django_cfg/modules/django_twilio/sms.py +94 -0
- django_cfg/modules/django_twilio/twilio_service.py +2 -3
- django_cfg/modules/django_twilio/unified.py +310 -0
- django_cfg/modules/django_twilio/utils.py +190 -0
- django_cfg/modules/django_twilio/whatsapp.py +137 -0
- django_cfg/modules/django_unfold/callbacks/base.py +198 -7
- django_cfg/modules/django_unfold/callbacks/main.py +102 -10
- django_cfg/modules/django_unfold/dashboard.py +65 -43
- django_cfg/modules/django_unfold/models/config.py +13 -12
- django_cfg/modules/django_unfold/models/navigation.py +8 -3
- django_cfg/modules/django_unfold/models/tabs.py +2 -2
- django_cfg/modules/django_unfold/templates/unfold/helpers/app_list.html +102 -0
- django_cfg/registry/core.py +24 -26
- django_cfg/registry/modules.py +5 -2
- django_cfg/registry/services.py +20 -3
- django_cfg/registry/third_party.py +8 -8
- django_cfg/static/admin/css/dashboard.css +260 -0
- django_cfg/static/admin/js/commands.js +171 -0
- django_cfg/static/admin/js/dashboard.js +126 -0
- django_cfg/templates/admin/components/management_commands.js +375 -0
- django_cfg/templates/admin/components/progress_bar.html +18 -23
- django_cfg/templates/admin/index.html +48 -20
- django_cfg/templates/admin/index_new.html +106 -0
- django_cfg/templates/admin/layouts/base_dashboard.html +60 -0
- django_cfg/templates/admin/layouts/dashboard_with_tabs.html +1 -20
- django_cfg/templates/admin/sections/commands_section.html +626 -0
- django_cfg/templates/admin/sections/overview_section.html +112 -0
- django_cfg/templates/admin/sections/stats_section.html +35 -0
- django_cfg/templates/admin/sections/system_section.html +99 -0
- django_cfg/templates/admin/snippets/components/CHARTS_GUIDE.md +322 -0
- django_cfg/templates/admin/snippets/components/activity_tracker.html +85 -47
- django_cfg/templates/admin/snippets/components/charts_section.html +154 -64
- django_cfg/templates/admin/snippets/components/django_commands.html +3 -3
- django_cfg/templates/admin/snippets/components/recent_activity_improved.html +25 -0
- django_cfg/templates/admin/snippets/components/recent_users_table.html +1 -1
- django_cfg/templates/admin/snippets/components/system_metrics.html +179 -93
- django_cfg/templates/admin/snippets/zones/zones_table.html +2 -2
- django_cfg/templatetags/django_cfg.py +7 -1
- django_cfg/utils/smart_defaults.py +4 -4
- django_cfg-1.4.0.dist-info/METADATA +920 -0
- {django_cfg-1.3.11.dist-info → django_cfg-1.4.0.dist-info}/RECORD +425 -196
- django_cfg/apps/accounts/utils/auth_email_service.py +0 -84
- django_cfg/apps/payments/services/providers/nowpayments/parsers.py +0 -879
- django_cfg/core/generation.py +0 -621
- django_cfg/management/commands/validate_config.py +0 -189
- django_cfg/models/database.py +0 -480
- django_cfg/models/drf.py +0 -272
- django_cfg/models/ngrok.py +0 -122
- django_cfg/models/services.py +0 -440
- django_cfg/models/tasks.py +0 -550
- django_cfg/modules/django_twilio/service.py +0 -942
- django_cfg/template_archive/django_sample.zip +0 -0
- django_cfg/templates/rest_framework/api.html +0 -12
- django_cfg/utils/toolkit.py +0 -703
- django_cfg-1.3.11.dist-info/METADATA +0 -1029
- /django_cfg/apps/accounts/management/commands/{test_otp.py → otp_test.py} +0 -0
- /django_cfg/core/{environment.py → environment/detector.py} +0 -0
- /django_cfg/models/{cors.py → api/cors.py} +0 -0
- /django_cfg/models/{jwt.py → api/jwt.py} +0 -0
- /django_cfg/models/{base.py → base/config.py} +0 -0
- /django_cfg/models/{cfg.py → base/module.py} +0 -0
- /django_cfg/models/{revolution.py → django/revolution.py} +0 -0
- /django_cfg/modules/{dramatiq_setup.py → django_tasks/dramatiq_setup.py} +0 -0
- {django_cfg-1.3.11.dist-info → django_cfg-1.4.0.dist-info}/WHEEL +0 -0
- {django_cfg-1.3.11.dist-info → django_cfg-1.4.0.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.3.11.dist-info → django_cfg-1.4.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,652 @@
|
|
1
|
+
"""
|
2
|
+
Core DjangoConfig Pydantic model.
|
3
|
+
|
4
|
+
This module contains ONLY the data model definition:
|
5
|
+
- Field definitions with types and defaults
|
6
|
+
- Field validators
|
7
|
+
- Simple properties
|
8
|
+
- NO business logic (moved to builders and services)
|
9
|
+
|
10
|
+
Total size: ~350 lines (down from 903 in original config.py)
|
11
|
+
"""
|
12
|
+
|
13
|
+
from typing import Dict, List, Optional, Any
|
14
|
+
from pathlib import Path
|
15
|
+
from pydantic import BaseModel, Field, field_validator, model_validator, PrivateAttr
|
16
|
+
|
17
|
+
from ..types.enums import EnvironmentMode, StartupInfoMode
|
18
|
+
from ..exceptions import ConfigurationError, ValidationError
|
19
|
+
from ...models import (
|
20
|
+
DatabaseConfig,
|
21
|
+
CacheConfig,
|
22
|
+
EmailConfig,
|
23
|
+
TelegramConfig,
|
24
|
+
UnfoldConfig,
|
25
|
+
DRFConfig,
|
26
|
+
SpectacularConfig,
|
27
|
+
LimitsConfig,
|
28
|
+
ApiKeys,
|
29
|
+
)
|
30
|
+
from ...models.tasks import TaskConfig
|
31
|
+
from ...models.payments import PaymentsConfig
|
32
|
+
from ...models.ngrok import NgrokConfig
|
33
|
+
from ...modules.django_cfg_rpc_client.config import DjangoCfgRPCConfig
|
34
|
+
|
35
|
+
|
36
|
+
class DjangoConfig(BaseModel):
|
37
|
+
"""
|
38
|
+
Base configuration class for Django projects.
|
39
|
+
|
40
|
+
This is a pure data model - all business logic is in separate classes:
|
41
|
+
- Apps list generation → InstalledAppsBuilder
|
42
|
+
- Middleware generation → MiddlewareBuilder
|
43
|
+
- Security settings → SecurityBuilder
|
44
|
+
- Settings generation → SettingsGenerator
|
45
|
+
|
46
|
+
Key Features:
|
47
|
+
- 100% type safety through Pydantic v2
|
48
|
+
- Environment-aware smart defaults
|
49
|
+
- Comprehensive validation
|
50
|
+
- Zero raw dictionary usage
|
51
|
+
|
52
|
+
Example:
|
53
|
+
```python
|
54
|
+
class MyProjectConfig(DjangoConfig):
|
55
|
+
project_name: str = "My Project"
|
56
|
+
databases: Dict[str, DatabaseConfig] = {
|
57
|
+
"default": DatabaseConfig(
|
58
|
+
engine="django.db.backends.postgresql",
|
59
|
+
name="${DATABASE_URL:mydb}",
|
60
|
+
)
|
61
|
+
}
|
62
|
+
|
63
|
+
config = MyProjectConfig()
|
64
|
+
settings = config.get_all_settings()
|
65
|
+
```
|
66
|
+
"""
|
67
|
+
|
68
|
+
model_config = {
|
69
|
+
"validate_assignment": True,
|
70
|
+
"extra": "forbid", # Forbid arbitrary fields for type safety
|
71
|
+
"env_prefix": "DJANGO_",
|
72
|
+
"populate_by_name": True,
|
73
|
+
"validate_default": True,
|
74
|
+
"str_strip_whitespace": True,
|
75
|
+
}
|
76
|
+
|
77
|
+
# === Environment Configuration ===
|
78
|
+
env_mode: EnvironmentMode = Field(
|
79
|
+
default=EnvironmentMode.PRODUCTION,
|
80
|
+
description="Environment mode: development, production, or test",
|
81
|
+
)
|
82
|
+
|
83
|
+
# === Project Information ===
|
84
|
+
project_name: str = Field(
|
85
|
+
...,
|
86
|
+
description="Human-readable project name",
|
87
|
+
min_length=1,
|
88
|
+
max_length=100,
|
89
|
+
)
|
90
|
+
|
91
|
+
project_logo: str = Field(
|
92
|
+
default="",
|
93
|
+
description="Project logo URL",
|
94
|
+
)
|
95
|
+
|
96
|
+
project_version: str = Field(
|
97
|
+
default="1.0.0",
|
98
|
+
description="Project version",
|
99
|
+
pattern=r"^\d+\.\d+\.\d+.*$",
|
100
|
+
)
|
101
|
+
|
102
|
+
project_description: str = Field(
|
103
|
+
default="",
|
104
|
+
description="Project description",
|
105
|
+
max_length=500,
|
106
|
+
)
|
107
|
+
|
108
|
+
# === Django CFG Features ===
|
109
|
+
startup_info_mode: StartupInfoMode = Field(
|
110
|
+
default=StartupInfoMode.FULL,
|
111
|
+
description="Startup information display mode: none (minimal), short (essential), full (complete)",
|
112
|
+
)
|
113
|
+
|
114
|
+
enable_support: bool = Field(
|
115
|
+
default=True,
|
116
|
+
description="Enable django-cfg Support application (tickets, messages, chat interface)",
|
117
|
+
)
|
118
|
+
|
119
|
+
enable_accounts: bool = Field(
|
120
|
+
default=False,
|
121
|
+
description="Enable django-cfg Accounts application (advanced user management, OTP, profiles, activity tracking)",
|
122
|
+
)
|
123
|
+
|
124
|
+
enable_newsletter: bool = Field(
|
125
|
+
default=False,
|
126
|
+
description="Enable django-cfg Newsletter application (email campaigns, subscriptions, bulk emails)",
|
127
|
+
)
|
128
|
+
|
129
|
+
enable_leads: bool = Field(
|
130
|
+
default=False,
|
131
|
+
description="Enable django-cfg Leads application (lead collection, contact forms, CRM integration)",
|
132
|
+
)
|
133
|
+
|
134
|
+
enable_knowbase: bool = Field(
|
135
|
+
default=False,
|
136
|
+
description="Enable django-cfg Knowledge Base application (documents, AI chat, embeddings, search)",
|
137
|
+
)
|
138
|
+
|
139
|
+
enable_agents: bool = Field(
|
140
|
+
default=False,
|
141
|
+
description="Enable django-cfg AI Agents application (agent definitions, executions, workflows, tools)",
|
142
|
+
)
|
143
|
+
|
144
|
+
enable_maintenance: bool = Field(
|
145
|
+
default=False,
|
146
|
+
description="Enable django-cfg Maintenance application (multi-site maintenance mode with Cloudflare)",
|
147
|
+
)
|
148
|
+
|
149
|
+
# === Payment System Configuration ===
|
150
|
+
payments: Optional[PaymentsConfig] = Field(
|
151
|
+
default=None,
|
152
|
+
description="Universal payment system configuration (providers, subscriptions, API keys, billing)",
|
153
|
+
)
|
154
|
+
|
155
|
+
# === URLs ===
|
156
|
+
site_url: str = Field(
|
157
|
+
default="http://localhost:3000",
|
158
|
+
description="Frontend site URL",
|
159
|
+
)
|
160
|
+
|
161
|
+
api_url: str = Field(
|
162
|
+
default="http://localhost:8000",
|
163
|
+
description="Backend API URL",
|
164
|
+
)
|
165
|
+
|
166
|
+
ticket_url: str = Field(
|
167
|
+
default="{site_url}/support/ticket/{uuid}",
|
168
|
+
description="Support ticket URL template. Use {site_url} and {uuid} placeholders",
|
169
|
+
)
|
170
|
+
|
171
|
+
otp_url: str = Field(
|
172
|
+
default="{site_url}/auth/otp/{code}",
|
173
|
+
description="OTP verification URL template. Use {site_url} and {code} placeholders",
|
174
|
+
)
|
175
|
+
|
176
|
+
# === Core Django Settings ===
|
177
|
+
secret_key: str = Field(
|
178
|
+
...,
|
179
|
+
description="Django SECRET_KEY",
|
180
|
+
min_length=50,
|
181
|
+
repr=False, # Don't show in repr for security
|
182
|
+
)
|
183
|
+
|
184
|
+
debug: bool = Field(
|
185
|
+
default=False,
|
186
|
+
description="Django DEBUG setting",
|
187
|
+
)
|
188
|
+
|
189
|
+
# === URL Configuration ===
|
190
|
+
root_urlconf: Optional[str] = Field(
|
191
|
+
default=None,
|
192
|
+
description="Django ROOT_URLCONF setting",
|
193
|
+
)
|
194
|
+
|
195
|
+
wsgi_application: Optional[str] = Field(
|
196
|
+
default=None,
|
197
|
+
description="Django WSGI_APPLICATION setting",
|
198
|
+
)
|
199
|
+
|
200
|
+
# === Custom User Model ===
|
201
|
+
auth_user_model: Optional[str] = Field(
|
202
|
+
default=None,
|
203
|
+
description="Custom user model (AUTH_USER_MODEL). If None and enable_accounts=True, uses 'django_cfg.apps.accounts.CustomUser'",
|
204
|
+
pattern=r"^[a-zA-Z_][a-zA-Z0-9_]*\.[a-zA-Z_][a-zA-Z0-9_]*$",
|
205
|
+
)
|
206
|
+
|
207
|
+
# === Project Applications ===
|
208
|
+
project_apps: List[str] = Field(
|
209
|
+
default_factory=list,
|
210
|
+
description="List of project-specific Django apps",
|
211
|
+
)
|
212
|
+
|
213
|
+
# === Database Configuration ===
|
214
|
+
databases: Dict[str, DatabaseConfig] = Field(
|
215
|
+
default_factory=dict,
|
216
|
+
description="Database connections",
|
217
|
+
)
|
218
|
+
|
219
|
+
# === Cache Configuration ===
|
220
|
+
cache_default: Optional[CacheConfig] = Field(
|
221
|
+
default=None,
|
222
|
+
description="Default cache backend",
|
223
|
+
)
|
224
|
+
|
225
|
+
cache_sessions: Optional[CacheConfig] = Field(
|
226
|
+
default=None,
|
227
|
+
description="Sessions cache backend",
|
228
|
+
)
|
229
|
+
|
230
|
+
# === Security Configuration ===
|
231
|
+
security_domains: List[str] = Field(
|
232
|
+
default_factory=list,
|
233
|
+
description="Domains for automatic security configuration (CORS, SSL, etc.)",
|
234
|
+
)
|
235
|
+
|
236
|
+
ssl_redirect: Optional[bool] = Field(
|
237
|
+
default=None,
|
238
|
+
description="Force SSL redirect on/off (None = auto based on domains and environment)",
|
239
|
+
)
|
240
|
+
|
241
|
+
# === CORS Configuration ===
|
242
|
+
cors_allow_headers: List[str] = Field(
|
243
|
+
default_factory=lambda: [
|
244
|
+
"accept",
|
245
|
+
"accept-encoding",
|
246
|
+
"authorization",
|
247
|
+
"content-type",
|
248
|
+
"dnt",
|
249
|
+
"origin",
|
250
|
+
"user-agent",
|
251
|
+
"x-csrftoken",
|
252
|
+
"x-requested-with",
|
253
|
+
"x-api-key",
|
254
|
+
"x-api-token",
|
255
|
+
],
|
256
|
+
description="CORS allowed headers with common defaults for API usage",
|
257
|
+
)
|
258
|
+
|
259
|
+
# === Services Configuration ===
|
260
|
+
email: Optional[EmailConfig] = Field(
|
261
|
+
default=None,
|
262
|
+
description="Email service configuration",
|
263
|
+
)
|
264
|
+
|
265
|
+
telegram: Optional[TelegramConfig] = Field(
|
266
|
+
default=None,
|
267
|
+
description="Telegram service configuration",
|
268
|
+
)
|
269
|
+
|
270
|
+
ngrok: Optional[NgrokConfig] = Field(
|
271
|
+
default=None,
|
272
|
+
description="Ngrok tunneling service configuration (for development/webhooks)",
|
273
|
+
)
|
274
|
+
|
275
|
+
# === Admin Interface Configuration ===
|
276
|
+
unfold: Optional[UnfoldConfig] = Field(
|
277
|
+
default=None,
|
278
|
+
description="Unfold admin interface configuration",
|
279
|
+
)
|
280
|
+
|
281
|
+
# === Frontend Configuration (Tailwind CSS) ===
|
282
|
+
tailwind_app_name: str = Field(
|
283
|
+
default="theme",
|
284
|
+
description="Name of the Tailwind theme app (django-tailwind integration)",
|
285
|
+
min_length=1,
|
286
|
+
max_length=50,
|
287
|
+
)
|
288
|
+
|
289
|
+
tailwind_version: int = Field(
|
290
|
+
default=4,
|
291
|
+
description="Tailwind CSS version (3 or 4)",
|
292
|
+
ge=3,
|
293
|
+
le=4,
|
294
|
+
)
|
295
|
+
|
296
|
+
enable_drf_tailwind: bool = Field(
|
297
|
+
default=True,
|
298
|
+
description="Enable modern Tailwind CSS theme for Django REST Framework Browsable API",
|
299
|
+
)
|
300
|
+
|
301
|
+
# === Background Task Processing ===
|
302
|
+
tasks: Optional[TaskConfig] = Field(
|
303
|
+
default=None,
|
304
|
+
description="Background task processing configuration (Dramatiq)",
|
305
|
+
)
|
306
|
+
|
307
|
+
# === RPC Client Configuration ===
|
308
|
+
django_cfg_rpc: Optional[DjangoCfgRPCConfig] = Field(
|
309
|
+
default=None,
|
310
|
+
description="Django-CFG RPC Client configuration (WebSocket RPC communication)",
|
311
|
+
)
|
312
|
+
|
313
|
+
# === API Configuration ===
|
314
|
+
drf: Optional[DRFConfig] = Field(
|
315
|
+
default=None,
|
316
|
+
description="Extended Django REST Framework configuration (supplements Revolution)",
|
317
|
+
)
|
318
|
+
|
319
|
+
spectacular: Optional[SpectacularConfig] = Field(
|
320
|
+
default=None,
|
321
|
+
description="Extended DRF Spectacular configuration (supplements Revolution)",
|
322
|
+
)
|
323
|
+
|
324
|
+
# === Limits Configuration ===
|
325
|
+
limits: Optional[LimitsConfig] = Field(
|
326
|
+
default=None,
|
327
|
+
description="Application limits configuration (file uploads, requests, etc.)",
|
328
|
+
)
|
329
|
+
|
330
|
+
# === API Keys Configuration ===
|
331
|
+
api_keys: Optional[ApiKeys] = Field(
|
332
|
+
default=None,
|
333
|
+
description="API keys for external services (OpenAI, OpenRouter, etc.)",
|
334
|
+
)
|
335
|
+
|
336
|
+
# === Middleware Configuration ===
|
337
|
+
custom_middleware: List[str] = Field(
|
338
|
+
default_factory=list,
|
339
|
+
description="Custom middleware classes (standard middleware added automatically)",
|
340
|
+
)
|
341
|
+
|
342
|
+
# === Internal State (Private) ===
|
343
|
+
_base_dir: Optional[Path] = PrivateAttr(default=None)
|
344
|
+
_django_settings: Optional[Dict[str, Any]] = PrivateAttr(default=None)
|
345
|
+
_service: Optional[Any] = PrivateAttr(default=None) # ConfigService instance
|
346
|
+
|
347
|
+
# === Field Validators ===
|
348
|
+
|
349
|
+
@field_validator("project_name")
|
350
|
+
@classmethod
|
351
|
+
def validate_project_name(cls, v: str) -> str:
|
352
|
+
"""Validate project name format."""
|
353
|
+
if not v.replace(" ", "").replace("-", "").replace("_", "").isalnum():
|
354
|
+
raise ValueError(
|
355
|
+
"Project name must contain only alphanumeric characters, "
|
356
|
+
"spaces, hyphens, and underscores"
|
357
|
+
)
|
358
|
+
return v
|
359
|
+
|
360
|
+
@field_validator("secret_key")
|
361
|
+
@classmethod
|
362
|
+
def validate_secret_key(cls, v: str) -> str:
|
363
|
+
"""Validate Django SECRET_KEY."""
|
364
|
+
if len(v) < 50:
|
365
|
+
raise ValueError("SECRET_KEY must be at least 50 characters long")
|
366
|
+
|
367
|
+
# Check for common insecure patterns (warning only, not error)
|
368
|
+
insecure_patterns = [
|
369
|
+
"django-insecure",
|
370
|
+
"change-me",
|
371
|
+
"your-secret-key",
|
372
|
+
"dev-key",
|
373
|
+
"test-key",
|
374
|
+
]
|
375
|
+
|
376
|
+
v_lower = v.lower()
|
377
|
+
for pattern in insecure_patterns:
|
378
|
+
if pattern in v_lower:
|
379
|
+
# This is a warning, not an error - allow for development
|
380
|
+
break
|
381
|
+
|
382
|
+
return v
|
383
|
+
|
384
|
+
@field_validator("project_apps")
|
385
|
+
@classmethod
|
386
|
+
def validate_project_apps(cls, v: List[str]) -> List[str]:
|
387
|
+
"""Validate project apps list."""
|
388
|
+
for app in v:
|
389
|
+
if not app:
|
390
|
+
raise ValueError("Empty app name in project_apps")
|
391
|
+
|
392
|
+
# Basic app name validation
|
393
|
+
if not app.replace(".", "").replace("_", "").isalnum():
|
394
|
+
raise ValueError(
|
395
|
+
f"Invalid app name '{app}': must contain only letters, "
|
396
|
+
f"numbers, dots, and underscores"
|
397
|
+
)
|
398
|
+
|
399
|
+
return v
|
400
|
+
|
401
|
+
@model_validator(mode="after")
|
402
|
+
def validate_configuration_consistency(self) -> "DjangoConfig":
|
403
|
+
"""Validate overall configuration consistency."""
|
404
|
+
# Ensure at least one database is configured
|
405
|
+
if not self.databases:
|
406
|
+
raise ConfigurationError(
|
407
|
+
"At least one database must be configured",
|
408
|
+
suggestions=["Add a 'default' database to the databases field"],
|
409
|
+
)
|
410
|
+
|
411
|
+
# Ensure 'default' database exists
|
412
|
+
if "default" not in self.databases:
|
413
|
+
raise ConfigurationError(
|
414
|
+
"'default' database is required",
|
415
|
+
context={"available_databases": list(self.databases.keys())},
|
416
|
+
suggestions=["Add a database with alias 'default'"],
|
417
|
+
)
|
418
|
+
|
419
|
+
# Validate database routing consistency
|
420
|
+
referenced_databases = set()
|
421
|
+
for alias, db_config in self.databases.items():
|
422
|
+
if db_config.migrate_to:
|
423
|
+
referenced_databases.add(db_config.migrate_to)
|
424
|
+
|
425
|
+
missing_databases = referenced_databases - set(self.databases.keys())
|
426
|
+
if missing_databases:
|
427
|
+
raise ConfigurationError(
|
428
|
+
f"Database routing references non-existent databases: {missing_databases}",
|
429
|
+
context={"available_databases": list(self.databases.keys())},
|
430
|
+
suggestions=[f"Add database configurations for: {', '.join(missing_databases)}"],
|
431
|
+
)
|
432
|
+
|
433
|
+
return self
|
434
|
+
|
435
|
+
def model_post_init(self, __context: Any) -> None:
|
436
|
+
"""
|
437
|
+
Initialize configuration after Pydantic validation.
|
438
|
+
|
439
|
+
Auto-detects environment from DJANGO_ENV, ENVIRONMENT, or ENV variables
|
440
|
+
if env_mode was not explicitly set.
|
441
|
+
"""
|
442
|
+
import os
|
443
|
+
|
444
|
+
# Only auto-detect if using default value (PRODUCTION)
|
445
|
+
# This allows explicit setting to override auto-detection
|
446
|
+
if self.env_mode == EnvironmentMode.PRODUCTION:
|
447
|
+
# Check if any env variable was explicitly set
|
448
|
+
env_vars = ['DJANGO_ENV', 'ENVIRONMENT', 'ENV']
|
449
|
+
for env_var in env_vars:
|
450
|
+
env_value = os.environ.get(env_var)
|
451
|
+
if env_value:
|
452
|
+
# Try to map to EnvironmentMode
|
453
|
+
env_normalized = env_value.lower().strip()
|
454
|
+
if env_normalized in ('dev', 'devel', 'develop', 'development', 'local'):
|
455
|
+
object.__setattr__(self, 'env_mode', EnvironmentMode.DEVELOPMENT)
|
456
|
+
break
|
457
|
+
elif env_normalized in ('prod', 'production'):
|
458
|
+
object.__setattr__(self, 'env_mode', EnvironmentMode.PRODUCTION)
|
459
|
+
break
|
460
|
+
elif env_normalized in ('test', 'testing'):
|
461
|
+
object.__setattr__(self, 'env_mode', EnvironmentMode.TEST)
|
462
|
+
break
|
463
|
+
|
464
|
+
# === Simple Properties (NO business logic!) ===
|
465
|
+
|
466
|
+
@property
|
467
|
+
def is_development(self) -> bool:
|
468
|
+
"""Check if running in development mode."""
|
469
|
+
return self.env_mode == EnvironmentMode.DEVELOPMENT
|
470
|
+
|
471
|
+
@property
|
472
|
+
def is_production(self) -> bool:
|
473
|
+
"""Check if running in production mode."""
|
474
|
+
return self.env_mode == EnvironmentMode.PRODUCTION
|
475
|
+
|
476
|
+
@property
|
477
|
+
def is_test(self) -> bool:
|
478
|
+
"""Check if running in test mode."""
|
479
|
+
return self.env_mode == EnvironmentMode.TEST
|
480
|
+
|
481
|
+
@property
|
482
|
+
def base_dir(self) -> Path:
|
483
|
+
"""
|
484
|
+
Get the base directory of the project.
|
485
|
+
|
486
|
+
Looks for manage.py in current directory and parents.
|
487
|
+
Falls back to current working directory if not found.
|
488
|
+
"""
|
489
|
+
if self._base_dir is None:
|
490
|
+
import os
|
491
|
+
|
492
|
+
# Start from current working directory
|
493
|
+
current_path = Path(os.path.dirname(os.path.abspath(__file__)))
|
494
|
+
|
495
|
+
# Look for manage.py in current directory and parents
|
496
|
+
for path in [current_path] + list(current_path.parents):
|
497
|
+
manage_py = path / "manage.py"
|
498
|
+
if manage_py.exists() and manage_py.is_file():
|
499
|
+
self._base_dir = path
|
500
|
+
break
|
501
|
+
|
502
|
+
# If still not found, use current directory
|
503
|
+
if self._base_dir is None:
|
504
|
+
self._base_dir = Path.cwd()
|
505
|
+
|
506
|
+
return self._base_dir
|
507
|
+
|
508
|
+
# === Facade Methods (delegate to service) ===
|
509
|
+
|
510
|
+
@property
|
511
|
+
def service(self) -> Any:
|
512
|
+
"""Lazy-load config service."""
|
513
|
+
if self._service is None:
|
514
|
+
from ..services.config_service import ConfigService
|
515
|
+
self._service = ConfigService(self)
|
516
|
+
return self._service
|
517
|
+
|
518
|
+
def get_installed_apps(self) -> List[str]:
|
519
|
+
"""Get complete INSTALLED_APPS list (delegates to service)."""
|
520
|
+
return self.service.get_installed_apps()
|
521
|
+
|
522
|
+
def get_middleware(self) -> List[str]:
|
523
|
+
"""Get complete MIDDLEWARE list (delegates to service)."""
|
524
|
+
return self.service.get_middleware()
|
525
|
+
|
526
|
+
def get_allowed_hosts(self) -> List[str]:
|
527
|
+
"""Get ALLOWED_HOSTS (delegates to service)."""
|
528
|
+
return self.service.get_allowed_hosts()
|
529
|
+
|
530
|
+
def get_all_settings(self) -> Dict[str, Any]:
|
531
|
+
"""
|
532
|
+
Generate complete Django settings dictionary.
|
533
|
+
|
534
|
+
Delegates to SettingsGenerator for actual generation.
|
535
|
+
|
536
|
+
Returns:
|
537
|
+
Complete Django settings ready for use
|
538
|
+
|
539
|
+
Raises:
|
540
|
+
ConfigurationError: If settings generation fails
|
541
|
+
"""
|
542
|
+
# Set as current config
|
543
|
+
from ..state.registry import set_current_config
|
544
|
+
set_current_config(self)
|
545
|
+
|
546
|
+
if self._django_settings is None:
|
547
|
+
from ..generation import SettingsGenerator
|
548
|
+
|
549
|
+
try:
|
550
|
+
self._django_settings = SettingsGenerator.generate(self)
|
551
|
+
except Exception as e:
|
552
|
+
raise ConfigurationError(
|
553
|
+
f"Failed to generate Django settings: {e}",
|
554
|
+
context={"config": self.model_dump(exclude={"_django_settings"})},
|
555
|
+
) from e
|
556
|
+
|
557
|
+
return self._django_settings
|
558
|
+
|
559
|
+
def get_ticket_url(self, ticket_uuid: str) -> str:
|
560
|
+
"""
|
561
|
+
Generate ticket URL using the configured template.
|
562
|
+
|
563
|
+
Args:
|
564
|
+
ticket_uuid: UUID of the support ticket
|
565
|
+
|
566
|
+
Returns:
|
567
|
+
Complete URL to the ticket
|
568
|
+
"""
|
569
|
+
return self.ticket_url.format(
|
570
|
+
site_url=self.site_url,
|
571
|
+
uuid=ticket_uuid,
|
572
|
+
)
|
573
|
+
|
574
|
+
def get_otp_url(self, otp_code: str) -> str:
|
575
|
+
"""
|
576
|
+
Generate OTP verification URL using the configured template.
|
577
|
+
|
578
|
+
Args:
|
579
|
+
otp_code: OTP verification code
|
580
|
+
|
581
|
+
Returns:
|
582
|
+
Complete URL to the OTP verification page
|
583
|
+
"""
|
584
|
+
return self.otp_url.format(
|
585
|
+
site_url=self.site_url,
|
586
|
+
code=otp_code,
|
587
|
+
)
|
588
|
+
|
589
|
+
def invalidate_cache(self) -> None:
|
590
|
+
"""
|
591
|
+
Invalidate cached Django settings.
|
592
|
+
|
593
|
+
Forces regeneration of settings on next call to get_all_settings().
|
594
|
+
Useful when configuration has changed and settings need to be regenerated.
|
595
|
+
|
596
|
+
Example:
|
597
|
+
>>> config.invalidate_cache()
|
598
|
+
>>> new_settings = config.get_all_settings() # Will regenerate
|
599
|
+
"""
|
600
|
+
self._django_settings = None
|
601
|
+
|
602
|
+
def model_dump_for_django(self, **kwargs) -> Dict[str, Any]:
|
603
|
+
"""
|
604
|
+
Serialize model data in Django-compatible format.
|
605
|
+
|
606
|
+
This method provides a dictionary representation suitable for Django settings,
|
607
|
+
with proper serialization of nested Pydantic models.
|
608
|
+
|
609
|
+
Args:
|
610
|
+
**kwargs: Additional arguments passed to model_dump()
|
611
|
+
|
612
|
+
Returns:
|
613
|
+
Dictionary with serialized configuration data
|
614
|
+
|
615
|
+
Example:
|
616
|
+
>>> config = DjangoConfig(project_name="My Project", ...)
|
617
|
+
>>> dump = config.model_dump_for_django()
|
618
|
+
>>> dump["project_name"]
|
619
|
+
'My Project'
|
620
|
+
"""
|
621
|
+
return self.model_dump(
|
622
|
+
mode="python",
|
623
|
+
exclude_none=False,
|
624
|
+
by_alias=False,
|
625
|
+
**kwargs
|
626
|
+
)
|
627
|
+
|
628
|
+
def should_enable_tasks(self) -> bool:
|
629
|
+
"""
|
630
|
+
Determine if background tasks should be enabled.
|
631
|
+
|
632
|
+
Tasks are enabled if:
|
633
|
+
1. Explicitly configured via tasks field
|
634
|
+
2. Knowledge base is enabled (requires background processing)
|
635
|
+
3. Agents are enabled (requires background processing)
|
636
|
+
|
637
|
+
Returns:
|
638
|
+
True if tasks should be enabled, False otherwise
|
639
|
+
"""
|
640
|
+
# Check if explicitly configured
|
641
|
+
if hasattr(self, 'tasks') and self.tasks and self.tasks.enabled:
|
642
|
+
return True
|
643
|
+
|
644
|
+
# Check if features that require tasks are enabled
|
645
|
+
if self.enable_knowbase or self.enable_agents:
|
646
|
+
return True
|
647
|
+
|
648
|
+
return False
|
649
|
+
|
650
|
+
|
651
|
+
# Export main class
|
652
|
+
__all__ = ["DjangoConfig"]
|
@@ -0,0 +1,11 @@
|
|
1
|
+
"""Builders for Django settings generation."""
|
2
|
+
|
3
|
+
from .apps_builder import InstalledAppsBuilder
|
4
|
+
from .middleware_builder import MiddlewareBuilder
|
5
|
+
from .security_builder import SecurityBuilder
|
6
|
+
|
7
|
+
__all__ = [
|
8
|
+
"InstalledAppsBuilder",
|
9
|
+
"MiddlewareBuilder",
|
10
|
+
"SecurityBuilder",
|
11
|
+
]
|