django-cfg 1.3.13__py3-none-any.whl → 1.4.3__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/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/agents/examples/__init__.py +3 -0
- django_cfg/apps/agents/examples/simple_example.py +161 -0
- 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/examples/__init__.py +3 -0
- django_cfg/apps/knowbase/examples/external_data_usage.py +191 -0
- 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/examples/vehicle_model_example.py +199 -0
- 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_currency/examples/__init__.py +3 -0
- django_cfg/modules/django_currency/examples/example_database_usage.py +144 -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_ipc_client/README.md +346 -0
- django_cfg/modules/django_ipc_client/__init__.py +51 -0
- django_cfg/modules/django_ipc_client/client.py +540 -0
- django_cfg/modules/django_ipc_client/config.py +207 -0
- django_cfg/modules/django_ipc_client/dashboard/README.md +517 -0
- django_cfg/modules/django_ipc_client/dashboard/UNFOLD_INTEGRATION.md +439 -0
- django_cfg/modules/django_ipc_client/dashboard/__init__.py +11 -0
- django_cfg/modules/django_ipc_client/dashboard/apps.py +22 -0
- django_cfg/modules/django_ipc_client/dashboard/monitor.py +435 -0
- django_cfg/modules/django_ipc_client/dashboard/static/django_ipc_dashboard/js/dashboard.js +373 -0
- django_cfg/modules/django_ipc_client/dashboard/templates/django_ipc_dashboard/base.html +76 -0
- django_cfg/modules/django_ipc_client/dashboard/templates/django_ipc_dashboard/dashboard.html +200 -0
- django_cfg/modules/django_ipc_client/dashboard/urls.py +22 -0
- django_cfg/modules/django_ipc_client/dashboard/urls_admin.py +9 -0
- django_cfg/modules/django_ipc_client/dashboard/views.py +251 -0
- django_cfg/modules/django_ipc_client/exceptions.py +201 -0
- 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/examples/component_class_example.html +156 -0
- 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.3.dist-info/METADATA +533 -0
- {django_cfg-1.3.13.dist-info → django_cfg-1.4.3.dist-info}/RECORD +432 -195
- 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.13.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.13.dist-info → django_cfg-1.4.3.dist-info}/WHEEL +0 -0
- {django_cfg-1.3.13.dist-info → django_cfg-1.4.3.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.3.13.dist-info → django_cfg-1.4.3.dist-info}/licenses/LICENSE +0 -0
django_cfg/core/config.py
CHANGED
@@ -1,903 +1,31 @@
|
|
1
1
|
"""
|
2
|
-
|
2
|
+
Convenience re-exports for django-cfg core.
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
- Proper type annotations for all fields
|
7
|
-
- No mutable default arguments
|
8
|
-
- Comprehensive validation and error handling
|
4
|
+
Usage:
|
5
|
+
from django_cfg.core.config import DjangoConfig, EnvironmentMode
|
9
6
|
"""
|
10
7
|
|
11
|
-
from
|
12
|
-
from
|
13
|
-
from
|
14
|
-
from
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
from django_cfg import (
|
20
|
-
ConfigurationError, ValidationError, EnvironmentError,
|
21
|
-
DatabaseConfig, CacheConfig, EmailConfig, TelegramConfig,
|
22
|
-
UnfoldConfig, DRFConfig, SpectacularConfig, LimitsConfig, ApiKeys
|
8
|
+
from .base.config_model import DjangoConfig
|
9
|
+
from .types.enums import EnvironmentMode, StartupInfoMode
|
10
|
+
from .constants import DEFAULT_APPS, DEFAULT_MIDDLEWARE
|
11
|
+
from .state.registry import (
|
12
|
+
get_current_config,
|
13
|
+
set_current_config,
|
14
|
+
clear_current_config,
|
23
15
|
)
|
24
|
-
from django_cfg.models.tasks import TaskConfig
|
25
|
-
from django_cfg.models.payments import PaymentsConfig
|
26
|
-
|
27
|
-
# Default apps
|
28
|
-
DEFAULT_APPS = [
|
29
|
-
# WhiteNoise for static files (must be before django.contrib.staticfiles)
|
30
|
-
"whitenoise.runserver_nostatic",
|
31
|
-
# Unfold
|
32
|
-
"unfold",
|
33
|
-
"unfold.contrib.filters", # optional, if special filters are needed
|
34
|
-
"unfold.contrib.forms", # optional, if special form elements are needed
|
35
|
-
"unfold.contrib.inlines", # optional, if special inlines are needed
|
36
|
-
"import_export", # django-import-export package
|
37
|
-
"unfold.contrib.import_export", # optional, if django-import-export package is used
|
38
|
-
"unfold.contrib.guardian", # optional, if django-guardian package is used
|
39
|
-
"unfold.contrib.simple_history", # optional, if django-simple-history package is used
|
40
|
-
"unfold.contrib.location_field", # optional, if django-location-field package is used
|
41
|
-
"unfold.contrib.constance", # optional, if django-constance package is used
|
42
|
-
# Django
|
43
|
-
"django.contrib.admin",
|
44
|
-
"django.contrib.auth",
|
45
|
-
"django.contrib.contenttypes",
|
46
|
-
"django.contrib.sessions",
|
47
|
-
"django.contrib.messages",
|
48
|
-
"django.contrib.staticfiles",
|
49
|
-
"django.contrib.humanize",
|
50
|
-
# Third-party
|
51
|
-
"corsheaders",
|
52
|
-
"rest_framework",
|
53
|
-
"rest_framework.authtoken",
|
54
|
-
"rest_framework_simplejwt",
|
55
|
-
"rest_framework_simplejwt.token_blacklist",
|
56
|
-
"rest_framework_nested",
|
57
|
-
"rangefilter",
|
58
|
-
"django_filters",
|
59
|
-
"drf_spectacular",
|
60
|
-
"drf_spectacular_sidecar",
|
61
|
-
"django_json_widget",
|
62
|
-
"django_extensions",
|
63
|
-
"constance",
|
64
|
-
"constance.backends.database",
|
65
|
-
# Note: django_dramatiq is added conditionally when tasks are enabled
|
66
|
-
# Django CFG
|
67
|
-
"django_cfg",
|
68
|
-
"django_revolution",
|
69
|
-
]
|
70
|
-
|
71
|
-
|
72
|
-
class EnvironmentMode(str, Enum):
|
73
|
-
"""Environment mode enumeration."""
|
74
|
-
DEVELOPMENT = "development"
|
75
|
-
PRODUCTION = "production"
|
76
|
-
TEST = "test"
|
77
|
-
|
78
|
-
@classmethod
|
79
|
-
def from_debug(cls, debug: bool) -> "EnvironmentMode":
|
80
|
-
"""Get environment mode from debug flag."""
|
81
|
-
return cls.DEVELOPMENT if debug else cls.PRODUCTION
|
82
|
-
|
83
|
-
|
84
|
-
class StartupInfoMode(str, Enum):
|
85
|
-
"""Startup information display mode."""
|
86
|
-
NONE = "none" # Minimal info only (version, environment, critical errors)
|
87
|
-
SHORT = "short" # Essential info (apps, endpoints, status, updates)
|
88
|
-
FULL = "full" # Complete info (everything from old system)
|
89
|
-
|
90
|
-
|
91
|
-
class DjangoConfig(BaseModel):
|
92
|
-
"""
|
93
|
-
Base configuration class for Django projects.
|
94
|
-
|
95
|
-
This is the core class that all Django project configurations inherit from.
|
96
|
-
It provides type-safe configuration management with intelligent defaults
|
97
|
-
and automatic Django settings generation.
|
98
|
-
|
99
|
-
Key Features:
|
100
|
-
- 100% type safety through Pydantic v2
|
101
|
-
- Environment-aware smart defaults
|
102
|
-
- Automatic Django settings generation
|
103
|
-
- Zero raw dictionary usage
|
104
|
-
- Comprehensive validation
|
105
|
-
|
106
|
-
Example:
|
107
|
-
```python
|
108
|
-
class MyProjectConfig(DjangoConfig):
|
109
|
-
project_name: str = "My Project"
|
110
|
-
databases: Dict[str, DatabaseConfig] = {
|
111
|
-
"default": DatabaseConfig(
|
112
|
-
engine="django.db.backends.postgresql",
|
113
|
-
name="${DATABASE_URL:mydb}",
|
114
|
-
)
|
115
|
-
}
|
116
|
-
|
117
|
-
config = MyProjectConfig()
|
118
|
-
```
|
119
|
-
"""
|
120
|
-
|
121
|
-
model_config = {
|
122
|
-
"validate_assignment": True,
|
123
|
-
"extra": "forbid", # Forbid arbitrary fields for type safety
|
124
|
-
"env_prefix": "DJANGO_",
|
125
|
-
"populate_by_name": True,
|
126
|
-
"validate_default": True,
|
127
|
-
"str_strip_whitespace": True,
|
128
|
-
}
|
129
|
-
|
130
|
-
# === Environment Configuration ===
|
131
|
-
env_mode: EnvironmentMode = Field(
|
132
|
-
default=EnvironmentMode.PRODUCTION,
|
133
|
-
description="Environment mode: development, production, or test",
|
134
|
-
)
|
135
|
-
|
136
|
-
# === Project Information ===
|
137
|
-
project_name: str = Field(
|
138
|
-
...,
|
139
|
-
description="Human-readable project name",
|
140
|
-
min_length=1,
|
141
|
-
max_length=100,
|
142
|
-
)
|
143
|
-
|
144
|
-
project_logo: str = Field(
|
145
|
-
default="",
|
146
|
-
description="Project logo URL",
|
147
|
-
)
|
148
|
-
|
149
|
-
project_version: str = Field(
|
150
|
-
default="1.0.0",
|
151
|
-
description="Project version",
|
152
|
-
pattern=r"^\d+\.\d+\.\d+.*$",
|
153
|
-
)
|
154
|
-
|
155
|
-
project_description: str = Field(
|
156
|
-
default="",
|
157
|
-
description="Project description",
|
158
|
-
max_length=500,
|
159
|
-
)
|
160
|
-
|
161
|
-
# === Django CFG Features ===
|
162
|
-
startup_info_mode: StartupInfoMode = Field(
|
163
|
-
default=StartupInfoMode.FULL,
|
164
|
-
description="Startup information display mode: none (minimal), short (essential), full (complete)",
|
165
|
-
)
|
166
|
-
|
167
|
-
enable_support: bool = Field(
|
168
|
-
default=True,
|
169
|
-
description="Enable django-cfg Support application (tickets, messages, chat interface)",
|
170
|
-
)
|
171
|
-
enable_accounts: bool = Field(
|
172
|
-
default=False,
|
173
|
-
description="Enable django-cfg Accounts application (advanced user management, OTP, profiles, activity tracking)",
|
174
|
-
)
|
175
|
-
enable_newsletter: bool = Field(
|
176
|
-
default=False,
|
177
|
-
description="Enable django-cfg Newsletter application (email campaigns, subscriptions, bulk emails)",
|
178
|
-
)
|
179
|
-
enable_leads: bool = Field(
|
180
|
-
default=False,
|
181
|
-
description="Enable django-cfg Leads application (lead collection, contact forms, CRM integration)",
|
182
|
-
)
|
183
|
-
enable_knowbase: bool = Field(
|
184
|
-
default=False,
|
185
|
-
description="Enable django-cfg Knowledge Base application (documents, AI chat, embeddings, search)",
|
186
|
-
)
|
187
|
-
enable_agents: bool = Field(
|
188
|
-
default=False,
|
189
|
-
description="Enable django-cfg AI Agents application (agent definitions, executions, workflows, tools)",
|
190
|
-
)
|
191
|
-
enable_maintenance: bool = Field(
|
192
|
-
default=False,
|
193
|
-
description="Enable django-cfg Maintenance application (multi-site maintenance mode with Cloudflare)",
|
194
|
-
)
|
195
|
-
# === Payment System Configuration ===
|
196
|
-
payments: Optional[PaymentsConfig] = Field(
|
197
|
-
default=None,
|
198
|
-
description="Universal payment system configuration (providers, subscriptions, API keys, billing)",
|
199
|
-
)
|
200
|
-
|
201
|
-
# === URLs ===
|
202
|
-
site_url: str = Field(default="http://localhost:3000", description="Frontend site URL")
|
203
|
-
api_url: str = Field(default="http://localhost:8000", description="Backend API URL")
|
204
|
-
ticket_url: str = Field(default="{site_url}/support/ticket/{uuid}", description="Support ticket URL template. Use {site_url} and {uuid} placeholders")
|
205
|
-
otp_url: str = Field(default="{site_url}/auth/otp/{code}", description="OTP verification URL template. Use {site_url} and {code} placeholders")
|
206
|
-
|
207
|
-
# === Core Django Settings ===
|
208
|
-
secret_key: str = Field(
|
209
|
-
...,
|
210
|
-
description="Django SECRET_KEY",
|
211
|
-
min_length=50,
|
212
|
-
repr=False, # Don't show in repr for security
|
213
|
-
)
|
214
|
-
|
215
|
-
debug: bool = Field(
|
216
|
-
default=False,
|
217
|
-
description="Django DEBUG setting",
|
218
|
-
)
|
219
|
-
|
220
|
-
# allowed_hosts removed - now auto-generated from security_domains
|
221
|
-
|
222
|
-
# === URL Configuration ===
|
223
|
-
root_urlconf: Optional[str] = Field(
|
224
|
-
default=None,
|
225
|
-
description="Django ROOT_URLCONF setting",
|
226
|
-
)
|
227
|
-
|
228
|
-
wsgi_application: Optional[str] = Field(
|
229
|
-
default=None,
|
230
|
-
description="Django WSGI_APPLICATION setting",
|
231
|
-
)
|
232
|
-
|
233
|
-
# === Custom User Model ===
|
234
|
-
auth_user_model: Optional[str] = Field(
|
235
|
-
default=None,
|
236
|
-
description="Custom user model (AUTH_USER_MODEL). If None and enable_accounts=True, uses 'django_cfg.apps.accounts.CustomUser'",
|
237
|
-
pattern=r"^[a-zA-Z_][a-zA-Z0-9_]*\.[a-zA-Z_][a-zA-Z0-9_]*$",
|
238
|
-
)
|
239
|
-
|
240
|
-
# === Project Applications ===
|
241
|
-
project_apps: List[str] = Field(
|
242
|
-
default_factory=list,
|
243
|
-
description="List of project-specific Django apps",
|
244
|
-
)
|
245
|
-
|
246
|
-
# === Database Configuration ===
|
247
|
-
databases: Dict[str, DatabaseConfig] = Field(
|
248
|
-
default_factory=dict,
|
249
|
-
description="Database connections",
|
250
|
-
)
|
251
|
-
|
252
|
-
# === Cache Configuration ===
|
253
|
-
cache_default: Optional[CacheConfig] = Field(
|
254
|
-
default=None,
|
255
|
-
description="Default cache backend",
|
256
|
-
)
|
257
|
-
|
258
|
-
cache_sessions: Optional[CacheConfig] = Field(
|
259
|
-
default=None,
|
260
|
-
description="Sessions cache backend",
|
261
|
-
)
|
262
|
-
|
263
|
-
# === Security Configuration ===
|
264
|
-
security_domains: List[str] = Field(
|
265
|
-
default_factory=list,
|
266
|
-
description="Domains for automatic security configuration (CORS, SSL, etc.)",
|
267
|
-
)
|
268
|
-
|
269
|
-
ssl_redirect: Optional[bool] = Field(
|
270
|
-
default=None,
|
271
|
-
description="Force SSL redirect on/off (None = auto based on domains and environment)",
|
272
|
-
)
|
273
|
-
|
274
|
-
# === CORS Configuration ===
|
275
|
-
cors_allow_headers: List[str] = Field(
|
276
|
-
default_factory=lambda: [
|
277
|
-
"accept",
|
278
|
-
"accept-encoding",
|
279
|
-
"authorization",
|
280
|
-
"content-type",
|
281
|
-
"dnt",
|
282
|
-
"origin",
|
283
|
-
"user-agent",
|
284
|
-
"x-csrftoken",
|
285
|
-
"x-requested-with",
|
286
|
-
"x-api-key",
|
287
|
-
"x-api-token",
|
288
|
-
],
|
289
|
-
description="CORS allowed headers with common defaults for API usage",
|
290
|
-
)
|
291
|
-
|
292
|
-
# === Services Configuration ===
|
293
|
-
email: Optional[EmailConfig] = Field(
|
294
|
-
default=None,
|
295
|
-
description="Email service configuration",
|
296
|
-
)
|
297
|
-
|
298
|
-
telegram: Optional[TelegramConfig] = Field(
|
299
|
-
default=None,
|
300
|
-
description="Telegram service configuration",
|
301
|
-
)
|
302
|
-
|
303
|
-
# === Admin Interface Configuration ===
|
304
|
-
unfold: Optional[UnfoldConfig] = Field(
|
305
|
-
default=None,
|
306
|
-
description="Unfold admin interface configuration",
|
307
|
-
)
|
308
|
-
|
309
|
-
# === Background Task Processing ===
|
310
|
-
tasks: Optional[TaskConfig] = Field(
|
311
|
-
default=None,
|
312
|
-
description="Background task processing configuration (Dramatiq)",
|
313
|
-
)
|
314
|
-
|
315
|
-
# === API Configuration ===
|
316
|
-
# Note: DRF base configuration is handled by django-revolution
|
317
|
-
# These fields provide additional/extended settings on top of Revolution
|
318
|
-
drf: Optional[DRFConfig] = Field(
|
319
|
-
default=None,
|
320
|
-
description="Extended Django REST Framework configuration (supplements Revolution)",
|
321
|
-
)
|
322
|
-
|
323
|
-
spectacular: Optional[SpectacularConfig] = Field(
|
324
|
-
default=None,
|
325
|
-
description="Extended DRF Spectacular configuration (supplements Revolution)",
|
326
|
-
)
|
327
|
-
|
328
|
-
# === Limits Configuration ===
|
329
|
-
limits: Optional[LimitsConfig] = Field(
|
330
|
-
default=None,
|
331
|
-
description="Application limits configuration (file uploads, requests, etc.)",
|
332
|
-
)
|
333
|
-
|
334
|
-
# === API Keys Configuration ===
|
335
|
-
api_keys: Optional[ApiKeys] = Field(
|
336
|
-
default=None,
|
337
|
-
description="API keys for external services (OpenAI, OpenRouter, etc.)",
|
338
|
-
)
|
339
|
-
|
340
|
-
# === Middleware Configuration ===
|
341
|
-
custom_middleware: List[str] = Field(
|
342
|
-
default_factory=list,
|
343
|
-
description="Custom middleware classes (standard middleware added automatically)",
|
344
|
-
)
|
345
|
-
|
346
|
-
# === Internal State ===
|
347
|
-
_base_dir: Optional[Path] = PrivateAttr(default=None)
|
348
|
-
_django_settings: Optional[Dict[str, Any]] = PrivateAttr(default=None)
|
349
|
-
|
350
|
-
def __init__(self, **data):
|
351
|
-
"""
|
352
|
-
Initialize configuration with automatic setup.
|
353
|
-
|
354
|
-
Performs the following setup steps:
|
355
|
-
1. Environment detection
|
356
|
-
2. Path resolution
|
357
|
-
3. Smart defaults application
|
358
|
-
4. Environment-specific configuration loading
|
359
|
-
"""
|
360
|
-
super().__init__(**data)
|
361
|
-
|
362
|
-
# Initialize internal state
|
363
|
-
self._auto_detect_env_mode()
|
364
|
-
self._resolve_paths()
|
365
|
-
self._apply_smart_defaults()
|
366
|
-
self._load_environment_config()
|
367
|
-
self._validate_configuration()
|
368
|
-
|
369
|
-
@field_validator("project_name")
|
370
|
-
@classmethod
|
371
|
-
def validate_project_name(cls, v: str) -> str:
|
372
|
-
"""Validate project name format."""
|
373
|
-
if not v.replace(" ", "").replace("-", "").replace("_", "").isalnum():
|
374
|
-
raise ValueError("Project name must contain only alphanumeric characters, " "spaces, hyphens, and underscores")
|
375
|
-
|
376
|
-
return v
|
377
|
-
|
378
|
-
@field_validator("secret_key")
|
379
|
-
@classmethod
|
380
|
-
def validate_secret_key(cls, v: str) -> str:
|
381
|
-
"""Validate Django SECRET_KEY."""
|
382
|
-
if len(v) < 50:
|
383
|
-
raise ValueError("SECRET_KEY must be at least 50 characters long")
|
384
|
-
|
385
|
-
# Check for common insecure patterns
|
386
|
-
insecure_patterns = [
|
387
|
-
"django-insecure",
|
388
|
-
"change-me",
|
389
|
-
"your-secret-key",
|
390
|
-
"dev-key",
|
391
|
-
"test-key",
|
392
|
-
]
|
393
|
-
|
394
|
-
v_lower = v.lower()
|
395
|
-
for pattern in insecure_patterns:
|
396
|
-
if pattern in v_lower:
|
397
|
-
# This is a warning, not an error - allow for development
|
398
|
-
break
|
399
|
-
|
400
|
-
return v
|
401
|
-
|
402
|
-
# validate_allowed_hosts removed - allowed_hosts now auto-generated from security_domains
|
403
|
-
|
404
|
-
@field_validator("project_apps")
|
405
|
-
@classmethod
|
406
|
-
def validate_project_apps(cls, v: List[str]) -> List[str]:
|
407
|
-
"""Validate project apps list."""
|
408
|
-
for app in v:
|
409
|
-
if not app:
|
410
|
-
raise ValueError("Empty app name in project_apps")
|
411
|
-
|
412
|
-
# Basic app name validation
|
413
|
-
if not app.replace(".", "").replace("_", "").isalnum():
|
414
|
-
raise ValueError(f"Invalid app name '{app}': must contain only letters, numbers, dots, and underscores")
|
415
|
-
|
416
|
-
return v
|
417
|
-
|
418
|
-
@model_validator(mode="after")
|
419
|
-
def validate_configuration_consistency(self) -> "DjangoConfig":
|
420
|
-
"""Validate overall configuration consistency."""
|
421
|
-
# Ensure at least one database is configured
|
422
|
-
if not self.databases:
|
423
|
-
raise ConfigurationError("At least one database must be configured", suggestions=["Add a 'default' database to the databases field"])
|
424
|
-
|
425
|
-
# Ensure 'default' database exists
|
426
|
-
if "default" not in self.databases:
|
427
|
-
raise ConfigurationError("'default' database is required", context={"available_databases": list(self.databases.keys())}, suggestions=["Add a database with alias 'default'"])
|
428
|
-
|
429
|
-
|
430
|
-
# Validate database routing consistency - check migrate_to references
|
431
|
-
referenced_databases = set()
|
432
|
-
for alias, db_config in self.databases.items():
|
433
|
-
if db_config.migrate_to:
|
434
|
-
referenced_databases.add(db_config.migrate_to)
|
435
|
-
|
436
|
-
missing_databases = referenced_databases - set(self.databases.keys())
|
437
|
-
if missing_databases:
|
438
|
-
raise ConfigurationError(f"Database routing references non-existent databases: {missing_databases}", context={"available_databases": list(self.databases.keys())}, suggestions=[f"Add database configurations for: {', '.join(missing_databases)}"])
|
439
|
-
|
440
|
-
return self
|
441
|
-
|
442
|
-
# === Environment Mode Properties ===
|
443
|
-
@property
|
444
|
-
def is_development(self) -> bool:
|
445
|
-
"""Check if running in development mode."""
|
446
|
-
return self.env_mode == EnvironmentMode.DEVELOPMENT
|
447
|
-
|
448
|
-
@property
|
449
|
-
def is_production(self) -> bool:
|
450
|
-
"""Check if running in production mode."""
|
451
|
-
return self.env_mode == EnvironmentMode.PRODUCTION
|
452
|
-
|
453
|
-
@property
|
454
|
-
def is_test(self) -> bool:
|
455
|
-
"""Check if running in test mode."""
|
456
|
-
return self.env_mode == EnvironmentMode.TEST
|
457
|
-
|
458
|
-
def _auto_detect_env_mode(self) -> None:
|
459
|
-
"""Auto-detect environment mode from various sources."""
|
460
|
-
import os
|
461
|
-
|
462
|
-
# Check environment variables first
|
463
|
-
env_var = os.getenv("DJANGO_ENV", "").lower()
|
464
|
-
if env_var in ["development", "dev"]:
|
465
|
-
self.env_mode = EnvironmentMode.DEVELOPMENT
|
466
|
-
elif env_var in ["production", "prod"]:
|
467
|
-
self.env_mode = EnvironmentMode.PRODUCTION
|
468
|
-
elif env_var in ["test", "testing"]:
|
469
|
-
self.env_mode = EnvironmentMode.TEST
|
470
|
-
elif hasattr(self, 'debug') and self.debug:
|
471
|
-
# Auto-detect from debug flag if no env var set
|
472
|
-
self.env_mode = EnvironmentMode.DEVELOPMENT
|
473
|
-
# Otherwise keep the default (PRODUCTION)
|
474
|
-
|
475
|
-
@property
|
476
|
-
def base_dir(self) -> Path:
|
477
|
-
"""Get the base directory of the project."""
|
478
|
-
if self._base_dir is None:
|
479
|
-
|
480
|
-
# Start from current working directory
|
481
|
-
current_path = Path(os.path.dirname(os.path.abspath(__file__)))
|
482
|
-
|
483
|
-
# Look for manage.py in current directory and parents
|
484
|
-
for path in [current_path] + list(current_path.parents):
|
485
|
-
manage_py = path / "manage.py"
|
486
|
-
if manage_py.exists() and manage_py.is_file():
|
487
|
-
self._base_dir = path
|
488
|
-
break
|
489
|
-
|
490
|
-
# If still not found, use current directory
|
491
|
-
if self._base_dir is None:
|
492
|
-
self._base_dir = Path.cwd()
|
493
|
-
|
494
|
-
return self._base_dir
|
495
|
-
|
496
|
-
def _resolve_paths(self) -> None:
|
497
|
-
"""Resolve project paths and auto-detect missing configuration."""
|
498
|
-
from django_cfg.utils.path_resolution import PathResolver
|
499
|
-
|
500
|
-
try:
|
501
|
-
# Find project root if not already set
|
502
|
-
if self._base_dir is None:
|
503
|
-
self._base_dir = PathResolver.find_project_root()
|
504
|
-
|
505
|
-
# Auto-detect URL configuration if not set
|
506
|
-
if not self.root_urlconf:
|
507
|
-
detected_urlconf = PathResolver.detect_root_urlconf(self._base_dir)
|
508
|
-
if detected_urlconf:
|
509
|
-
self.root_urlconf = detected_urlconf
|
510
|
-
|
511
|
-
# Auto-detect WSGI application if not set
|
512
|
-
if not self.wsgi_application:
|
513
|
-
detected_wsgi = PathResolver.detect_wsgi_application(self._base_dir)
|
514
|
-
if detected_wsgi:
|
515
|
-
self.wsgi_application = detected_wsgi
|
516
|
-
|
517
|
-
except Exception as e:
|
518
|
-
raise ConfigurationError(f"Failed to resolve project paths: {e}", suggestions=["Ensure manage.py exists in your project root", "Set root_urlconf and wsgi_application explicitly"]) from e
|
519
|
-
|
520
|
-
def _apply_smart_defaults(self) -> None:
|
521
|
-
"""Apply environment-aware smart defaults."""
|
522
|
-
from django_cfg.utils.smart_defaults import SmartDefaults
|
523
|
-
|
524
|
-
try:
|
525
|
-
# Apply cache defaults
|
526
|
-
if self.cache_default:
|
527
|
-
self.cache_default = SmartDefaults.configure_cache_backend(self.cache_default, self.env_mode, self.debug)
|
528
|
-
|
529
|
-
if self.cache_sessions:
|
530
|
-
self.cache_sessions = SmartDefaults.configure_cache_backend(self.cache_sessions, self.env_mode, self.debug)
|
531
|
-
|
532
|
-
# Apply email defaults
|
533
|
-
if self.email:
|
534
|
-
self.email = SmartDefaults.configure_email_backend(self.email, self.env_mode, self.debug)
|
535
|
-
|
536
|
-
except Exception as e:
|
537
|
-
raise ConfigurationError(f"Failed to apply smart defaults: {e}", context={"environment": self.env_mode, "debug": self.debug}) from e
|
538
|
-
|
539
|
-
def _load_environment_config(self) -> None:
|
540
|
-
"""Load environment-specific configuration from YAML files."""
|
541
|
-
# TODO: Implement environment-specific configuration loading
|
542
|
-
# This will be implemented when EnvironmentConfig model is created
|
543
|
-
pass
|
544
|
-
|
545
|
-
def _validate_configuration(self) -> None:
|
546
|
-
"""Perform final configuration validation."""
|
547
|
-
from django_cfg.core.validation import ConfigurationValidator
|
548
|
-
|
549
|
-
try:
|
550
|
-
errors = ConfigurationValidator.validate(self)
|
551
|
-
if errors:
|
552
|
-
raise ValidationError(f"Configuration validation failed: {len(errors)} errors found", context={"errors": errors}, suggestions=["Fix the validation errors listed in context"])
|
553
|
-
except Exception as e:
|
554
|
-
if isinstance(e, ValidationError):
|
555
|
-
raise
|
556
|
-
raise ConfigurationError(f"Configuration validation failed: {e}") from e
|
557
|
-
|
558
|
-
def get_all_settings(self) -> Dict[str, Any]:
|
559
|
-
"""
|
560
|
-
Generate complete Django settings dictionary.
|
561
|
-
|
562
|
-
Returns:
|
563
|
-
Complete Django settings ready for use
|
564
|
-
|
565
|
-
Raises:
|
566
|
-
ConfigurationError: If settings generation fails
|
567
|
-
"""
|
568
|
-
# Automatically set this config as the current global config
|
569
|
-
set_current_config(self)
|
570
|
-
|
571
|
-
if self._django_settings is None:
|
572
|
-
from django_cfg.core.generation import SettingsGenerator
|
573
|
-
|
574
|
-
try:
|
575
|
-
self._django_settings = SettingsGenerator.generate(self)
|
576
|
-
except Exception as e:
|
577
|
-
raise ConfigurationError(f"Failed to generate Django settings: {e}", context={"config": self.model_dump(exclude={"_django_settings"})}) from e
|
578
|
-
|
579
|
-
return self._django_settings
|
580
|
-
|
581
|
-
def get_ticket_url(self, ticket_uuid: str) -> str:
|
582
|
-
"""
|
583
|
-
Generate ticket URL using the configured template.
|
584
|
-
|
585
|
-
Args:
|
586
|
-
ticket_uuid: UUID of the support ticket
|
587
|
-
|
588
|
-
Returns:
|
589
|
-
Complete URL to the ticket
|
590
|
-
"""
|
591
|
-
return self.ticket_url.format(
|
592
|
-
site_url=self.site_url,
|
593
|
-
uuid=ticket_uuid
|
594
|
-
)
|
595
|
-
|
596
|
-
def get_otp_url(self, otp_code: str) -> str:
|
597
|
-
"""
|
598
|
-
Generate OTP verification URL using the configured template.
|
599
|
-
|
600
|
-
Args:
|
601
|
-
otp_code: OTP verification code
|
602
|
-
|
603
|
-
Returns:
|
604
|
-
Complete URL to the OTP verification page
|
605
|
-
"""
|
606
|
-
return self.otp_url.format(
|
607
|
-
site_url=self.site_url,
|
608
|
-
code=otp_code
|
609
|
-
)
|
610
|
-
|
611
|
-
def should_enable_tasks(self) -> bool:
|
612
|
-
"""
|
613
|
-
Determine if background tasks should be enabled.
|
614
|
-
|
615
|
-
Tasks are enabled if:
|
616
|
-
1. Explicitly configured via tasks field
|
617
|
-
2. Knowledge base is enabled (requires background processing)
|
618
|
-
3. Agents are enabled (requires background processing)
|
619
|
-
|
620
|
-
Returns:
|
621
|
-
True if tasks should be enabled, False otherwise
|
622
|
-
"""
|
623
|
-
# Check if explicitly configured
|
624
|
-
if hasattr(self, 'tasks') and self.tasks and self.tasks.enabled:
|
625
|
-
return True
|
626
|
-
|
627
|
-
# Check if features that require tasks are enabled
|
628
|
-
if self.enable_knowbase or self.enable_agents:
|
629
|
-
return True
|
630
|
-
|
631
|
-
# Check if agents module requires tasks
|
632
|
-
if self.enable_agents:
|
633
|
-
return True
|
634
|
-
|
635
|
-
return False
|
636
|
-
|
637
|
-
def get_enabled_apps(self) -> List[str]:
|
638
|
-
"""
|
639
|
-
Get list of enabled django-cfg apps.
|
640
|
-
"""
|
641
|
-
|
642
|
-
apps = [
|
643
|
-
"django_cfg.apps.api.health",
|
644
|
-
"django_cfg.apps.api.commands",
|
645
|
-
]
|
646
|
-
|
647
|
-
if self.enable_support:
|
648
|
-
apps.append("django_cfg.apps.support")
|
649
|
-
if self.enable_accounts:
|
650
|
-
apps.append("django_cfg.apps.accounts")
|
651
|
-
if self.enable_newsletter:
|
652
|
-
apps.append("django_cfg.apps.newsletter")
|
653
|
-
if self.enable_leads:
|
654
|
-
apps.append("django_cfg.apps.leads")
|
655
|
-
if self.enable_knowbase:
|
656
|
-
apps.append("django_cfg.apps.knowbase")
|
657
|
-
if self.enable_agents:
|
658
|
-
apps.append("django_cfg.apps.agents")
|
659
|
-
if self.enable_maintenance:
|
660
|
-
apps.append("django_cfg.apps.maintenance")
|
661
|
-
if self.payments and self.payments.enabled:
|
662
|
-
apps.append("django_cfg.apps.payments")
|
663
|
-
return apps
|
664
|
-
|
665
|
-
def get_installed_apps(self) -> List[str]:
|
666
|
-
"""
|
667
|
-
Get complete list of installed Django apps.
|
668
|
-
|
669
|
-
Returns:
|
670
|
-
List of Django app names
|
671
|
-
"""
|
672
|
-
# Start with DEFAULT_APPS but handle accounts specially
|
673
|
-
apps = []
|
674
|
-
|
675
|
-
# Add apps before admin
|
676
|
-
for app in DEFAULT_APPS:
|
677
|
-
if app == "django.contrib.admin":
|
678
|
-
# Insert accounts before admin if enabled (for proper migration order)
|
679
|
-
if self.enable_accounts:
|
680
|
-
apps.append("django_cfg.apps.accounts")
|
681
|
-
apps.append(app)
|
682
|
-
|
683
|
-
# Add other django-cfg built-in apps after standard apps
|
684
|
-
if self.enable_support:
|
685
|
-
apps.append("django_cfg.apps.support")
|
686
|
-
if self.enable_newsletter:
|
687
|
-
apps.append("django_cfg.apps.newsletter")
|
688
|
-
if self.enable_leads:
|
689
|
-
apps.append("django_cfg.apps.leads")
|
690
|
-
if self.enable_knowbase:
|
691
|
-
apps.append("django_cfg.apps.knowbase")
|
692
|
-
if self.enable_agents:
|
693
|
-
apps.append("django_cfg.apps.agents")
|
694
|
-
if self.enable_maintenance:
|
695
|
-
apps.append("django_cfg.apps.maintenance")
|
696
|
-
if self.payments and self.payments.enabled:
|
697
|
-
apps.append("django_cfg.apps.payments")
|
698
|
-
|
699
|
-
# Auto-enable tasks if needed
|
700
|
-
if self.should_enable_tasks():
|
701
|
-
apps.append("django_dramatiq") # Add django_dramatiq first
|
702
|
-
apps.append("django_cfg.apps.tasks")
|
703
|
-
|
704
|
-
# Auto-detect dashboard apps from Unfold callback
|
705
|
-
dashboard_apps = self._get_dashboard_apps_from_callback()
|
706
|
-
apps.extend(dashboard_apps)
|
707
|
-
|
708
|
-
# Add project-specific apps
|
709
|
-
apps.extend(self.project_apps)
|
710
|
-
|
711
|
-
# Remove duplicates while preserving order
|
712
|
-
seen = set()
|
713
|
-
apps = [app for app in apps if not (app in seen or seen.add(app))]
|
714
|
-
|
715
|
-
return apps
|
716
|
-
|
717
|
-
def _get_dashboard_apps_from_callback(self) -> List[str]:
|
718
|
-
"""
|
719
|
-
Auto-detect dashboard apps from Unfold dashboard_callback setting.
|
720
|
-
|
721
|
-
Extracts app names from callback paths like:
|
722
|
-
- "api.dashboard.callbacks.main_dashboard_callback" -> ["api.dashboard"]
|
723
|
-
- "myproject.admin.callbacks.dashboard" -> ["myproject.admin"]
|
724
|
-
|
725
|
-
Returns:
|
726
|
-
List of dashboard app names to add to INSTALLED_APPS
|
727
|
-
"""
|
728
|
-
dashboard_apps = []
|
729
|
-
|
730
|
-
if not self.unfold or not self.unfold.theme:
|
731
|
-
return dashboard_apps
|
732
|
-
|
733
|
-
callback_path = getattr(self.unfold.theme, "dashboard_callback", None)
|
734
|
-
if not callback_path:
|
735
|
-
return dashboard_apps
|
736
|
-
|
737
|
-
try:
|
738
|
-
# Parse callback path: "api.dashboard.callbacks.main_dashboard_callback"
|
739
|
-
# Extract app part: "api.dashboard"
|
740
|
-
parts = callback_path.split(".")
|
741
|
-
|
742
|
-
# Look for common callback patterns
|
743
|
-
callback_indicators = ["callbacks", "views", "handlers"]
|
744
|
-
|
745
|
-
# Find the callback indicator and extract app path before it
|
746
|
-
app_parts = []
|
747
|
-
for i, part in enumerate(parts):
|
748
|
-
if part in callback_indicators:
|
749
|
-
app_parts = parts[:i] # Everything before the callback indicator
|
750
|
-
break
|
751
|
-
|
752
|
-
# If no callback indicator found, assume last part is function name
|
753
|
-
if not app_parts and len(parts) > 1:
|
754
|
-
app_parts = parts[:-1] # Everything except the last part
|
755
|
-
|
756
|
-
if app_parts:
|
757
|
-
app_name = ".".join(app_parts)
|
758
|
-
dashboard_apps.append(app_name)
|
759
|
-
|
760
|
-
except Exception:
|
761
|
-
# If parsing fails, silently continue - dashboard callback is optional
|
762
|
-
pass
|
763
|
-
|
764
|
-
return dashboard_apps
|
765
|
-
|
766
|
-
def get_middleware(self) -> List[str]:
|
767
|
-
"""
|
768
|
-
Get complete middleware stack.
|
769
|
-
|
770
|
-
Returns:
|
771
|
-
List of middleware class paths
|
772
|
-
"""
|
773
|
-
# Standard Django middleware (always included)
|
774
|
-
middleware = [
|
775
|
-
"django.middleware.security.SecurityMiddleware",
|
776
|
-
"whitenoise.middleware.WhiteNoiseMiddleware", # Add WhiteNoise for static files
|
777
|
-
"django.contrib.sessions.middleware.SessionMiddleware",
|
778
|
-
"django.middleware.common.CommonMiddleware",
|
779
|
-
"django.middleware.csrf.CsrfViewMiddleware",
|
780
|
-
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
781
|
-
"django.contrib.messages.middleware.MessageMiddleware",
|
782
|
-
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
783
|
-
]
|
784
|
-
|
785
|
-
# Add CORS middleware if security domains are configured
|
786
|
-
if self.security_domains:
|
787
|
-
middleware.insert(2, "corsheaders.middleware.CorsMiddleware") # Insert after WhiteNoise
|
788
|
-
|
789
|
-
# Add Django CFG middleware based on enabled features
|
790
|
-
if self.enable_accounts:
|
791
|
-
middleware.append("django_cfg.middleware.UserActivityMiddleware")
|
792
|
-
|
793
|
-
# Add payments middleware if enabled
|
794
|
-
if self.payments and self.payments.enabled:
|
795
|
-
middleware.extend(self.payments.get_middleware_classes())
|
796
|
-
|
797
|
-
# Add custom middleware
|
798
|
-
middleware.extend(self.custom_middleware)
|
799
|
-
|
800
|
-
return middleware
|
801
|
-
|
802
|
-
def get_allowed_hosts(self) -> List[str]:
|
803
|
-
"""
|
804
|
-
Generate ALLOWED_HOSTS from security_domains.
|
805
|
-
|
806
|
-
Returns:
|
807
|
-
List of allowed hosts including localhost for development
|
808
|
-
"""
|
809
|
-
allowed_hosts = []
|
810
|
-
|
811
|
-
# Add security domains if configured
|
812
|
-
if self.security_domains:
|
813
|
-
|
814
|
-
for domain in self.security_domains:
|
815
|
-
# Parse URL properly
|
816
|
-
if "://" in domain:
|
817
|
-
# Use urlparse to extract hostname correctly
|
818
|
-
parsed_url = urlparse(domain)
|
819
|
-
hostname = parsed_url.netloc.split(":")[0] # Remove port if present
|
820
|
-
else:
|
821
|
-
hostname = domain
|
822
|
-
|
823
|
-
# Add hostname itself
|
824
|
-
if hostname not in allowed_hosts:
|
825
|
-
allowed_hosts.append(hostname)
|
826
|
-
|
827
|
-
# Add www subdomain if not already a subdomain and not localhost
|
828
|
-
if not hostname.startswith("www.") and not hostname.startswith("*.") and not hostname.startswith("localhost") and not hostname.startswith("127.0.0.1"):
|
829
|
-
www_hostname = f"www.{hostname}"
|
830
|
-
if www_hostname not in allowed_hosts:
|
831
|
-
allowed_hosts.append(www_hostname)
|
832
|
-
|
833
|
-
# Always allow localhost and 127.0.0.1 for development
|
834
|
-
localhost_hosts = ["localhost", "127.0.0.1", "0.0.0.0"]
|
835
|
-
for host in localhost_hosts:
|
836
|
-
if host not in allowed_hosts:
|
837
|
-
allowed_hosts.append(host)
|
838
|
-
|
839
|
-
# If no domains configured, allow all (development mode)
|
840
|
-
if not self.security_domains:
|
841
|
-
allowed_hosts = ["*"]
|
842
|
-
|
843
|
-
return allowed_hosts
|
844
|
-
|
845
|
-
def get_site_url(self, path: str = "") -> str:
|
846
|
-
"""
|
847
|
-
Get the site URL with optional path.
|
848
|
-
|
849
|
-
Args:
|
850
|
-
path: Optional path to append to site URL
|
851
|
-
|
852
|
-
Returns:
|
853
|
-
Complete URL with path
|
854
|
-
"""
|
855
|
-
if path:
|
856
|
-
path = path.lstrip("/")
|
857
|
-
return f"{self.site_url.rstrip('/')}/{path}"
|
858
|
-
return self.site_url
|
859
|
-
|
860
|
-
|
861
|
-
def invalidate_cache(self) -> None:
|
862
|
-
"""Invalidate cached Django settings to force regeneration."""
|
863
|
-
self._django_settings = None
|
864
|
-
|
865
|
-
def model_dump_for_django(self) -> Dict[str, Any]:
|
866
|
-
"""
|
867
|
-
Dump model data in format suitable for Django settings.
|
868
|
-
|
869
|
-
Returns:
|
870
|
-
Model data with internal fields excluded
|
871
|
-
"""
|
872
|
-
return self.model_dump(exclude={"_base_dir", "_django_settings"}, exclude_none=True)
|
873
|
-
|
874
|
-
|
875
|
-
# Global config instance for access from other modules
|
876
|
-
_current_config = None
|
877
|
-
|
878
|
-
def get_current_config():
|
879
|
-
"""
|
880
|
-
Get the current DjangoConfig instance.
|
881
|
-
|
882
|
-
Returns:
|
883
|
-
The current DjangoConfig instance or None if not set
|
884
|
-
"""
|
885
|
-
global _current_config
|
886
|
-
return _current_config
|
887
|
-
|
888
|
-
def set_current_config(config: DjangoConfig):
|
889
|
-
"""
|
890
|
-
Set the current DjangoConfig instance.
|
891
|
-
|
892
|
-
Args:
|
893
|
-
config: The DjangoConfig instance to set as current
|
894
|
-
"""
|
895
|
-
global _current_config
|
896
|
-
_current_config = config
|
897
16
|
|
898
|
-
#
|
17
|
+
# Public API
|
899
18
|
__all__ = [
|
19
|
+
# Main config
|
900
20
|
"DjangoConfig",
|
21
|
+
# Enums
|
22
|
+
"EnvironmentMode",
|
23
|
+
"StartupInfoMode",
|
24
|
+
# Constants
|
25
|
+
"DEFAULT_APPS",
|
26
|
+
"DEFAULT_MIDDLEWARE",
|
27
|
+
# Global state
|
901
28
|
"get_current_config",
|
902
29
|
"set_current_config",
|
30
|
+
"clear_current_config",
|
903
31
|
]
|