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
@@ -42,7 +42,7 @@ class OTPViewSet(viewsets.GenericViewSet):
|
|
42
42
|
500: OTPErrorResponseSerializer,
|
43
43
|
},
|
44
44
|
)
|
45
|
-
@action(detail=False, methods=["post"], url_path="request")
|
45
|
+
@action(detail=False, methods=["post"], url_path="request", url_name="request")
|
46
46
|
def request_otp(self, request):
|
47
47
|
"""Request OTP code to email or phone."""
|
48
48
|
serializer = OTPRequestSerializer(data=request.data)
|
@@ -111,7 +111,7 @@ class OTPViewSet(viewsets.GenericViewSet):
|
|
111
111
|
410: OTPErrorResponseSerializer,
|
112
112
|
},
|
113
113
|
)
|
114
|
-
@action(detail=False, methods=["post"], url_path="verify")
|
114
|
+
@action(detail=False, methods=["post"], url_path="verify", url_name="verify")
|
115
115
|
def verify_otp(self, request):
|
116
116
|
"""Verify OTP code and return JWT tokens."""
|
117
117
|
serializer = OTPVerifySerializer(data=request.data)
|
@@ -20,7 +20,7 @@ from drf_spectacular.utils import extend_schema, OpenApiParameter
|
|
20
20
|
from drf_spectacular.types import OpenApiTypes
|
21
21
|
from twilio.request_validator import RequestValidator
|
22
22
|
|
23
|
-
from django_cfg.core.
|
23
|
+
from django_cfg.core.state import get_current_config
|
24
24
|
from ..models import TwilioResponse, OTPSecret
|
25
25
|
from ..serializers.webhook import TwilioWebhookSerializer
|
26
26
|
|
@@ -14,7 +14,7 @@ from pydantic_ai.models.openai import OpenAIChatModel
|
|
14
14
|
from pydantic_ai.providers.openrouter import OpenRouterProvider
|
15
15
|
from pydantic_ai.providers.openai import OpenAIProvider
|
16
16
|
|
17
|
-
from django_cfg.modules.
|
17
|
+
from django_cfg.modules.django_logging import get_logger
|
18
18
|
from django_cfg.modules.base import BaseCfgModule
|
19
19
|
from .exceptions import ExecutionError, ConfigurationError
|
20
20
|
|
@@ -21,13 +21,13 @@ from django.utils import timezone
|
|
21
21
|
logger = logging.getLogger(__name__)
|
22
22
|
|
23
23
|
|
24
|
-
def
|
25
|
-
"""Check if user is
|
26
|
-
return user.is_authenticated and user.
|
24
|
+
def is_staff_user(user):
|
25
|
+
"""Check if user is staff member."""
|
26
|
+
return user.is_authenticated and user.is_staff
|
27
27
|
|
28
28
|
|
29
29
|
@require_http_methods(["GET"])
|
30
|
-
@user_passes_test(
|
30
|
+
@user_passes_test(is_staff_user)
|
31
31
|
def list_commands_view(request):
|
32
32
|
"""
|
33
33
|
List all available Django management commands.
|
@@ -81,7 +81,7 @@ def list_commands_view(request):
|
|
81
81
|
|
82
82
|
@csrf_exempt
|
83
83
|
@require_http_methods(["POST"])
|
84
|
-
@user_passes_test(
|
84
|
+
@user_passes_test(is_staff_user)
|
85
85
|
def execute_command_view(request):
|
86
86
|
"""
|
87
87
|
Execute a Django management command and stream output in real-time.
|
@@ -117,106 +117,89 @@ def execute_command_view(request):
|
|
117
117
|
"error": f"Command '{command_name}' not found",
|
118
118
|
"available_commands": list(available_commands.keys()),
|
119
119
|
}, status=400)
|
120
|
-
|
121
|
-
# Security check -
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
if command_name in dangerous_commands:
|
120
|
+
|
121
|
+
# Security check - use same filtering as dashboard
|
122
|
+
from django_cfg.modules.django_unfold.callbacks.base import is_command_allowed
|
123
|
+
|
124
|
+
app_name = available_commands.get(command_name)
|
125
|
+
if not is_command_allowed(command_name, app_name):
|
128
126
|
return JsonResponse({
|
129
|
-
"status": "error",
|
130
|
-
"error": f"Command '{command_name}' is not allowed via
|
131
|
-
"suggestion": "
|
127
|
+
"status": "error",
|
128
|
+
"error": f"Command '{command_name}' is not allowed via web interface for security reasons",
|
129
|
+
"suggestion": "Only safe django_cfg commands and whitelisted utilities can be executed via web.",
|
132
130
|
}, status=403)
|
133
131
|
|
134
132
|
# Create streaming response generator
|
135
133
|
def stream_command_execution():
|
136
134
|
"""Generator that yields command output in SSE format."""
|
137
135
|
start_time = time.time()
|
138
|
-
|
136
|
+
|
139
137
|
# Send start event
|
140
138
|
yield f"data: {json.dumps({'type': 'start', 'command': command_name, 'args': args})}\n\n"
|
141
|
-
|
139
|
+
|
142
140
|
try:
|
143
|
-
#
|
144
|
-
import
|
141
|
+
# Capture command output using StringIO
|
142
|
+
from io import StringIO
|
145
143
|
import sys
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
if key.startswith('--'):
|
173
|
-
cmd.append(key)
|
174
|
-
if value is not True: # Boolean flags don't need values
|
175
|
-
cmd.append(str(value))
|
176
|
-
else:
|
177
|
-
cmd.append(f"--{key}")
|
178
|
-
if value is not True:
|
179
|
-
cmd.append(str(value))
|
180
|
-
|
181
|
-
# Start process
|
182
|
-
process = subprocess.Popen(
|
183
|
-
cmd,
|
184
|
-
stdout=subprocess.PIPE,
|
185
|
-
stderr=subprocess.STDOUT,
|
186
|
-
universal_newlines=True,
|
187
|
-
bufsize=1,
|
188
|
-
cwd=project_root
|
189
|
-
)
|
190
|
-
|
144
|
+
|
145
|
+
# Create output buffer
|
146
|
+
output_buffer = StringIO()
|
147
|
+
|
148
|
+
# Redirect stdout/stderr to buffer
|
149
|
+
old_stdout = sys.stdout
|
150
|
+
old_stderr = sys.stderr
|
151
|
+
sys.stdout = output_buffer
|
152
|
+
sys.stderr = output_buffer
|
153
|
+
|
154
|
+
try:
|
155
|
+
# Execute Django command directly using call_command
|
156
|
+
call_command(command_name, *args, **options)
|
157
|
+
return_code = 0
|
158
|
+
except Exception as e:
|
159
|
+
# Command execution failed
|
160
|
+
output_buffer.write(f"\nError: {str(e)}\n")
|
161
|
+
return_code = 1
|
162
|
+
finally:
|
163
|
+
# Restore stdout/stderr
|
164
|
+
sys.stdout = old_stdout
|
165
|
+
sys.stderr = old_stderr
|
166
|
+
|
167
|
+
# Get all output
|
168
|
+
output = output_buffer.getvalue()
|
169
|
+
|
191
170
|
# Stream output line by line
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
# Wait for process to complete
|
198
|
-
return_code = process.wait()
|
171
|
+
if output:
|
172
|
+
for line in output.split('\n'):
|
173
|
+
if line.strip():
|
174
|
+
yield f"data: {json.dumps({'type': 'output', 'line': line})}\n\n"
|
175
|
+
|
199
176
|
execution_time = time.time() - start_time
|
200
|
-
|
177
|
+
|
201
178
|
# Send completion event
|
202
179
|
yield f"data: {json.dumps({'type': 'complete', 'return_code': return_code, 'execution_time': round(execution_time, 2)})}\n\n"
|
203
|
-
|
180
|
+
|
204
181
|
# Log command execution
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
182
|
+
if return_code == 0:
|
183
|
+
logger.info(
|
184
|
+
f"Command executed: {command_name} {' '.join(args)} "
|
185
|
+
f"by user {request.user.username} in {execution_time:.2f}s"
|
186
|
+
)
|
187
|
+
else:
|
188
|
+
logger.error(
|
189
|
+
f"Command failed: {command_name} {' '.join(args)} "
|
190
|
+
f"by user {request.user.username} in {execution_time:.2f}s"
|
191
|
+
)
|
192
|
+
|
210
193
|
except Exception as cmd_error:
|
211
194
|
execution_time = time.time() - start_time
|
212
|
-
|
195
|
+
|
213
196
|
logger.error(
|
214
197
|
f"Command failed: {command_name} {' '.join(args)} "
|
215
198
|
f"by user {request.user.username}: {cmd_error}"
|
216
199
|
)
|
217
|
-
|
200
|
+
|
218
201
|
# Send error event
|
219
|
-
yield f"data: {json.dumps({'type': 'error', '
|
202
|
+
yield f"data: {json.dumps({'type': 'error', 'message': str(cmd_error), 'execution_time': round(execution_time, 2)})}\n\n"
|
220
203
|
|
221
204
|
# Return streaming response
|
222
205
|
response = StreamingHttpResponse(
|
@@ -243,7 +226,7 @@ def execute_command_view(request):
|
|
243
226
|
|
244
227
|
|
245
228
|
@require_http_methods(["GET"])
|
246
|
-
@user_passes_test(
|
229
|
+
@user_passes_test(is_staff_user)
|
247
230
|
def command_help_view(request, command_name):
|
248
231
|
"""
|
249
232
|
Get help information for a specific command.
|
@@ -0,0 +1,269 @@
|
|
1
|
+
"""
|
2
|
+
Django CFG Health Check DRF Views
|
3
|
+
|
4
|
+
DRF browsable API views with Tailwind theme support.
|
5
|
+
"""
|
6
|
+
|
7
|
+
import os
|
8
|
+
import time
|
9
|
+
import psutil
|
10
|
+
from datetime import datetime
|
11
|
+
from typing import Dict, Any
|
12
|
+
|
13
|
+
from django.conf import settings
|
14
|
+
from django.db import connections
|
15
|
+
from django.core.cache import cache
|
16
|
+
from django.utils import timezone
|
17
|
+
|
18
|
+
from rest_framework.views import APIView
|
19
|
+
from rest_framework.response import Response
|
20
|
+
from rest_framework import status
|
21
|
+
from rest_framework.permissions import AllowAny
|
22
|
+
|
23
|
+
from django_cfg.core.integration import get_current_version
|
24
|
+
from .serializers import HealthCheckSerializer, QuickHealthSerializer
|
25
|
+
|
26
|
+
|
27
|
+
class DRFHealthCheckView(APIView):
|
28
|
+
"""
|
29
|
+
Django CFG comprehensive health check endpoint with DRF Browsable API.
|
30
|
+
|
31
|
+
Auto-discovers configuration from DjangoConfig and checks:
|
32
|
+
- All configured databases
|
33
|
+
- Cache connectivity
|
34
|
+
- System resources
|
35
|
+
- Configuration status
|
36
|
+
|
37
|
+
This endpoint uses DRF Browsable API with Tailwind CSS theme! 🎨
|
38
|
+
"""
|
39
|
+
|
40
|
+
permission_classes = [AllowAny] # Public endpoint
|
41
|
+
serializer_class = HealthCheckSerializer # For schema generation
|
42
|
+
|
43
|
+
def get(self, request):
|
44
|
+
"""Return comprehensive health check data."""
|
45
|
+
# Get DjangoConfig instance
|
46
|
+
try:
|
47
|
+
config = getattr(settings, 'config', None)
|
48
|
+
|
49
|
+
health_data = {
|
50
|
+
"status": "healthy",
|
51
|
+
"timestamp": timezone.now(),
|
52
|
+
"service": config.project_name if config else "Django CFG",
|
53
|
+
"version": get_current_version(),
|
54
|
+
"checks": {}
|
55
|
+
}
|
56
|
+
except Exception:
|
57
|
+
health_data = {
|
58
|
+
"status": "healthy",
|
59
|
+
"timestamp": timezone.now(),
|
60
|
+
"service": "Django CFG",
|
61
|
+
"version": get_current_version(),
|
62
|
+
"checks": {}
|
63
|
+
}
|
64
|
+
|
65
|
+
# Database connectivity check
|
66
|
+
try:
|
67
|
+
db_status = self._check_databases()
|
68
|
+
health_data["checks"]["databases"] = db_status
|
69
|
+
except Exception as e:
|
70
|
+
health_data["checks"]["databases"] = {
|
71
|
+
"status": "error",
|
72
|
+
"error": str(e)
|
73
|
+
}
|
74
|
+
health_data["status"] = "unhealthy"
|
75
|
+
|
76
|
+
# Cache availability check
|
77
|
+
try:
|
78
|
+
cache_status = self._check_cache()
|
79
|
+
health_data["checks"]["cache"] = cache_status
|
80
|
+
except Exception as e:
|
81
|
+
health_data["checks"]["cache"] = {
|
82
|
+
"status": "error",
|
83
|
+
"error": str(e)
|
84
|
+
}
|
85
|
+
if health_data["status"] != "unhealthy":
|
86
|
+
health_data["status"] = "degraded"
|
87
|
+
|
88
|
+
# System resources check
|
89
|
+
try:
|
90
|
+
system_status = self._check_system_resources()
|
91
|
+
health_data["checks"]["system"] = system_status
|
92
|
+
except Exception as e:
|
93
|
+
health_data["checks"]["system"] = {
|
94
|
+
"status": "error",
|
95
|
+
"error": str(e)
|
96
|
+
}
|
97
|
+
|
98
|
+
# Environment info
|
99
|
+
health_data["environment"] = {
|
100
|
+
"debug": getattr(settings, 'DEBUG', False),
|
101
|
+
"django_env": os.getenv("DJANGO_ENV", "development"),
|
102
|
+
"python_version": f"{os.sys.version_info.major}.{os.sys.version_info.minor}.{os.sys.version_info.micro}",
|
103
|
+
}
|
104
|
+
|
105
|
+
# Return appropriate HTTP status
|
106
|
+
http_status = status.HTTP_200_OK
|
107
|
+
if health_data["status"] == "unhealthy":
|
108
|
+
http_status = status.HTTP_503_SERVICE_UNAVAILABLE
|
109
|
+
elif health_data["status"] == "degraded":
|
110
|
+
http_status = status.HTTP_200_OK # Still operational
|
111
|
+
|
112
|
+
return Response(health_data, status=http_status)
|
113
|
+
|
114
|
+
def _check_databases(self) -> Dict[str, Any]:
|
115
|
+
"""Check all configured database connections."""
|
116
|
+
db_results = {}
|
117
|
+
|
118
|
+
# Get all configured databases
|
119
|
+
database_names = list(getattr(settings, 'DATABASES', {}).keys())
|
120
|
+
|
121
|
+
for db_name in database_names:
|
122
|
+
try:
|
123
|
+
start_time = time.time()
|
124
|
+
conn = connections[db_name]
|
125
|
+
|
126
|
+
with conn.cursor() as cursor:
|
127
|
+
cursor.execute("SELECT 1")
|
128
|
+
cursor.fetchone()
|
129
|
+
|
130
|
+
response_time = (time.time() - start_time) * 1000 # ms
|
131
|
+
|
132
|
+
db_results[db_name] = {
|
133
|
+
"status": "healthy",
|
134
|
+
"response_time_ms": round(response_time, 2),
|
135
|
+
"engine": conn.settings_dict.get("ENGINE", "unknown"),
|
136
|
+
}
|
137
|
+
|
138
|
+
except Exception as e:
|
139
|
+
db_results[db_name] = {
|
140
|
+
"status": "error",
|
141
|
+
"error": str(e)[:100], # Truncate long errors
|
142
|
+
}
|
143
|
+
|
144
|
+
# Overall database status
|
145
|
+
all_healthy = all(
|
146
|
+
db["status"] == "healthy"
|
147
|
+
for db in db_results.values()
|
148
|
+
) if db_results else False
|
149
|
+
|
150
|
+
return {
|
151
|
+
"status": "healthy" if all_healthy else "error",
|
152
|
+
"databases": db_results,
|
153
|
+
"total_databases": len(db_results),
|
154
|
+
}
|
155
|
+
|
156
|
+
def _check_cache(self) -> Dict[str, Any]:
|
157
|
+
"""Check cache connectivity and performance."""
|
158
|
+
try:
|
159
|
+
test_key = "django_cfg_health_check"
|
160
|
+
test_value = f"test_{int(time.time())}"
|
161
|
+
|
162
|
+
# Test cache write
|
163
|
+
start_time = time.time()
|
164
|
+
cache.set(test_key, test_value, timeout=60)
|
165
|
+
write_time = (time.time() - start_time) * 1000
|
166
|
+
|
167
|
+
# Test cache read
|
168
|
+
start_time = time.time()
|
169
|
+
cached_value = cache.get(test_key)
|
170
|
+
read_time = (time.time() - start_time) * 1000
|
171
|
+
|
172
|
+
# Cleanup
|
173
|
+
cache.delete(test_key)
|
174
|
+
|
175
|
+
if cached_value == test_value:
|
176
|
+
return {
|
177
|
+
"status": "healthy",
|
178
|
+
"write_time_ms": round(write_time, 2),
|
179
|
+
"read_time_ms": round(read_time, 2),
|
180
|
+
"backend": getattr(settings, "CACHES", {}).get("default", {}).get("BACKEND", "unknown"),
|
181
|
+
}
|
182
|
+
else:
|
183
|
+
return {
|
184
|
+
"status": "error",
|
185
|
+
"error": "Cache read/write mismatch"
|
186
|
+
}
|
187
|
+
|
188
|
+
except Exception as e:
|
189
|
+
return {
|
190
|
+
"status": "error",
|
191
|
+
"error": str(e)
|
192
|
+
}
|
193
|
+
|
194
|
+
def _check_system_resources(self) -> Dict[str, Any]:
|
195
|
+
"""Check system resource usage."""
|
196
|
+
try:
|
197
|
+
# CPU usage
|
198
|
+
cpu_percent = psutil.cpu_percent(interval=1)
|
199
|
+
|
200
|
+
# Memory usage
|
201
|
+
memory = psutil.virtual_memory()
|
202
|
+
|
203
|
+
# Disk usage
|
204
|
+
disk = psutil.disk_usage('/')
|
205
|
+
|
206
|
+
# System uptime
|
207
|
+
boot_time = datetime.fromtimestamp(psutil.boot_time())
|
208
|
+
uptime = datetime.now() - boot_time
|
209
|
+
|
210
|
+
return {
|
211
|
+
"status": "healthy",
|
212
|
+
"cpu": {
|
213
|
+
"percent": cpu_percent,
|
214
|
+
"count": psutil.cpu_count(),
|
215
|
+
},
|
216
|
+
"memory": {
|
217
|
+
"percent": memory.percent,
|
218
|
+
"used_gb": round(memory.used / (1024**3), 2),
|
219
|
+
"total_gb": round(memory.total / (1024**3), 2),
|
220
|
+
},
|
221
|
+
"disk": {
|
222
|
+
"percent": round((disk.used / disk.total) * 100, 2),
|
223
|
+
"used_gb": round(disk.used / (1024**3), 2),
|
224
|
+
"total_gb": round(disk.total / (1024**3), 2),
|
225
|
+
},
|
226
|
+
"uptime": {
|
227
|
+
"days": uptime.days,
|
228
|
+
"hours": uptime.seconds // 3600,
|
229
|
+
"boot_time": boot_time.isoformat(),
|
230
|
+
},
|
231
|
+
"process_count": len(psutil.pids()),
|
232
|
+
}
|
233
|
+
|
234
|
+
except Exception as e:
|
235
|
+
return {
|
236
|
+
"status": "error",
|
237
|
+
"error": str(e)
|
238
|
+
}
|
239
|
+
|
240
|
+
|
241
|
+
class DRFQuickHealthView(APIView):
|
242
|
+
"""
|
243
|
+
Quick health check for load balancers with DRF Browsable API.
|
244
|
+
|
245
|
+
This endpoint uses DRF Browsable API with Tailwind CSS theme! 🎨
|
246
|
+
"""
|
247
|
+
|
248
|
+
permission_classes = [AllowAny] # Public endpoint
|
249
|
+
serializer_class = QuickHealthSerializer # For schema generation
|
250
|
+
|
251
|
+
def get(self, request):
|
252
|
+
"""Return minimal health status."""
|
253
|
+
try:
|
254
|
+
# Just check main database
|
255
|
+
conn = connections["default"]
|
256
|
+
with conn.cursor() as cursor:
|
257
|
+
cursor.execute("SELECT 1")
|
258
|
+
|
259
|
+
return Response({
|
260
|
+
"status": "ok",
|
261
|
+
"timestamp": timezone.now(),
|
262
|
+
})
|
263
|
+
|
264
|
+
except Exception as e:
|
265
|
+
return Response({
|
266
|
+
"status": "error",
|
267
|
+
"error": str(e),
|
268
|
+
"timestamp": timezone.now(),
|
269
|
+
}, status=status.HTTP_503_SERVICE_UNAVAILABLE)
|
@@ -0,0 +1,45 @@
|
|
1
|
+
"""
|
2
|
+
Django CFG Health Check Serializers
|
3
|
+
|
4
|
+
DRF serializers for health check endpoints with Tailwind browsable API.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from rest_framework import serializers
|
8
|
+
|
9
|
+
|
10
|
+
class HealthCheckSerializer(serializers.Serializer):
|
11
|
+
"""Serializer for health check response."""
|
12
|
+
|
13
|
+
status = serializers.CharField(
|
14
|
+
help_text="Overall health status: healthy, degraded, or unhealthy"
|
15
|
+
)
|
16
|
+
timestamp = serializers.DateTimeField(
|
17
|
+
help_text="Timestamp of the health check"
|
18
|
+
)
|
19
|
+
service = serializers.CharField(
|
20
|
+
help_text="Service name"
|
21
|
+
)
|
22
|
+
version = serializers.CharField(
|
23
|
+
help_text="Django-CFG version"
|
24
|
+
)
|
25
|
+
checks = serializers.DictField(
|
26
|
+
help_text="Detailed health checks for databases, cache, and system"
|
27
|
+
)
|
28
|
+
environment = serializers.DictField(
|
29
|
+
help_text="Environment information"
|
30
|
+
)
|
31
|
+
|
32
|
+
|
33
|
+
class QuickHealthSerializer(serializers.Serializer):
|
34
|
+
"""Serializer for quick health check response."""
|
35
|
+
|
36
|
+
status = serializers.CharField(
|
37
|
+
help_text="Quick health status: ok or error"
|
38
|
+
)
|
39
|
+
timestamp = serializers.DateTimeField(
|
40
|
+
help_text="Timestamp of the health check"
|
41
|
+
)
|
42
|
+
error = serializers.CharField(
|
43
|
+
required=False,
|
44
|
+
help_text="Error message if health check failed"
|
45
|
+
)
|
@@ -3,9 +3,14 @@ Django CFG Health Check URLs.
|
|
3
3
|
"""
|
4
4
|
|
5
5
|
from django.urls import path
|
6
|
-
from . import views
|
6
|
+
from . import views, drf_views
|
7
7
|
|
8
8
|
urlpatterns = [
|
9
|
+
# Original JSON endpoints
|
9
10
|
path('', views.HealthCheckView.as_view(), name='django_cfg_health'),
|
10
11
|
path('quick/', views.QuickHealthView.as_view(), name='django_cfg_quick_health'),
|
12
|
+
|
13
|
+
# DRF Browsable API endpoints with Tailwind theme
|
14
|
+
path('drf/', drf_views.DRFHealthCheckView.as_view(), name='django_cfg_drf_health'),
|
15
|
+
path('drf/quick/', drf_views.DRFQuickHealthView.as_view(), name='django_cfg_drf_quick_health'),
|
11
16
|
]
|
@@ -0,0 +1,13 @@
|
|
1
|
+
"""
|
2
|
+
Shared admin actions for knowbase.
|
3
|
+
|
4
|
+
Provides reusable actions for admin interfaces.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from .visibility_actions import VisibilityActions, mark_as_public, mark_as_private
|
8
|
+
|
9
|
+
__all__ = [
|
10
|
+
'VisibilityActions',
|
11
|
+
'mark_as_public',
|
12
|
+
'mark_as_private',
|
13
|
+
]
|
@@ -0,0 +1,56 @@
|
|
1
|
+
"""
|
2
|
+
Shared admin actions for visibility management.
|
3
|
+
|
4
|
+
Provides consistent actions for toggling public/private status across
|
5
|
+
all knowbase admin interfaces.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from django.contrib import messages
|
9
|
+
from django_cfg.modules.django_admin import action, ActionVariant
|
10
|
+
|
11
|
+
|
12
|
+
class VisibilityActions:
|
13
|
+
"""Shared actions for visibility management."""
|
14
|
+
|
15
|
+
@staticmethod
|
16
|
+
@action(description="Mark as public", variant=ActionVariant.SUCCESS)
|
17
|
+
def mark_as_public(modeladmin, request, queryset):
|
18
|
+
"""
|
19
|
+
Mark selected items as public.
|
20
|
+
|
21
|
+
Args:
|
22
|
+
modeladmin: Admin class instance
|
23
|
+
request: HTTP request object
|
24
|
+
queryset: Selected items queryset
|
25
|
+
|
26
|
+
Returns:
|
27
|
+
None (displays success message)
|
28
|
+
"""
|
29
|
+
updated = queryset.update(is_public=True)
|
30
|
+
messages.success(request, f"Marked {updated} item(s) as public.")
|
31
|
+
|
32
|
+
@staticmethod
|
33
|
+
@action(description="Mark as private", variant=ActionVariant.WARNING)
|
34
|
+
def mark_as_private(modeladmin, request, queryset):
|
35
|
+
"""
|
36
|
+
Mark selected items as private.
|
37
|
+
|
38
|
+
Args:
|
39
|
+
modeladmin: Admin class instance
|
40
|
+
request: HTTP request object
|
41
|
+
queryset: Selected items queryset
|
42
|
+
|
43
|
+
Returns:
|
44
|
+
None (displays warning message)
|
45
|
+
"""
|
46
|
+
updated = queryset.update(is_public=False)
|
47
|
+
messages.warning(request, f"Marked {updated} item(s) as private.")
|
48
|
+
|
49
|
+
|
50
|
+
# Aliases for backward compatibility and consistency
|
51
|
+
# DocumentAdmin uses "mark_as_*" while DocumentCategoryAdmin used "make_*"
|
52
|
+
# These aliases ensure both naming conventions work
|
53
|
+
mark_as_public = VisibilityActions.mark_as_public
|
54
|
+
mark_as_private = VisibilityActions.mark_as_private
|
55
|
+
make_public = VisibilityActions.mark_as_public
|
56
|
+
make_private = VisibilityActions.mark_as_private
|