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
@@ -0,0 +1,207 @@
|
|
1
|
+
"""
|
2
|
+
Django-CFG RPC Client Configuration.
|
3
|
+
|
4
|
+
Pydantic 2 configuration model for RPC client integration.
|
5
|
+
Follows django-cfg patterns for modular configuration.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from pydantic import BaseModel, Field, field_validator
|
9
|
+
|
10
|
+
|
11
|
+
class DjangoCfgRPCConfig(BaseModel):
|
12
|
+
"""
|
13
|
+
Django-CFG RPC Client configuration module.
|
14
|
+
|
15
|
+
Configures Redis-based RPC communication between Django and
|
16
|
+
django-cfg-rpc WebSocket servers.
|
17
|
+
|
18
|
+
Example:
|
19
|
+
>>> from django_cfg import DjangoConfig
|
20
|
+
>>> from django_cfg.modules.django_ipc_client import DjangoCfgRPCConfig
|
21
|
+
>>>
|
22
|
+
>>> config = DjangoConfig(
|
23
|
+
... django_ipc=DjangoCfgRPCConfig(
|
24
|
+
... enabled=True,
|
25
|
+
... redis_url="redis://localhost:6379/2",
|
26
|
+
... rpc_timeout=30
|
27
|
+
... )
|
28
|
+
... )
|
29
|
+
"""
|
30
|
+
|
31
|
+
# Module metadata
|
32
|
+
module_name: str = Field(
|
33
|
+
default="django_ipc_client",
|
34
|
+
frozen=True,
|
35
|
+
description="Module name for django-cfg integration",
|
36
|
+
)
|
37
|
+
|
38
|
+
enabled: bool = Field(
|
39
|
+
default=False,
|
40
|
+
description="Enable Django-CFG RPC client",
|
41
|
+
)
|
42
|
+
|
43
|
+
# Redis configuration
|
44
|
+
redis_url: str = Field(
|
45
|
+
default="redis://localhost:6379/2",
|
46
|
+
description="Redis URL for RPC communication (dedicated database recommended)",
|
47
|
+
examples=[
|
48
|
+
"redis://localhost:6379/2",
|
49
|
+
"redis://:password@localhost:6379/2",
|
50
|
+
"redis://redis-server:6379/2",
|
51
|
+
],
|
52
|
+
)
|
53
|
+
|
54
|
+
redis_max_connections: int = Field(
|
55
|
+
default=50,
|
56
|
+
ge=10,
|
57
|
+
le=500,
|
58
|
+
description="Maximum Redis connection pool size",
|
59
|
+
)
|
60
|
+
|
61
|
+
# RPC settings
|
62
|
+
rpc_timeout: int = Field(
|
63
|
+
default=30,
|
64
|
+
ge=5,
|
65
|
+
le=300,
|
66
|
+
description="Default RPC call timeout (seconds)",
|
67
|
+
)
|
68
|
+
|
69
|
+
request_stream: str = Field(
|
70
|
+
default="stream:requests",
|
71
|
+
min_length=1,
|
72
|
+
max_length=100,
|
73
|
+
description="Redis Stream name for RPC requests",
|
74
|
+
)
|
75
|
+
|
76
|
+
consumer_group: str = Field(
|
77
|
+
default="rpc_group",
|
78
|
+
min_length=1,
|
79
|
+
max_length=100,
|
80
|
+
description="Redis Streams consumer group name (on server side)",
|
81
|
+
)
|
82
|
+
|
83
|
+
stream_maxlen: int = Field(
|
84
|
+
default=10000,
|
85
|
+
ge=1000,
|
86
|
+
le=100000,
|
87
|
+
description="Maximum stream length (XADD MAXLEN)",
|
88
|
+
)
|
89
|
+
|
90
|
+
# Response settings
|
91
|
+
response_key_prefix: str = Field(
|
92
|
+
default="list:response:",
|
93
|
+
min_length=1,
|
94
|
+
max_length=50,
|
95
|
+
description="Prefix for response list keys",
|
96
|
+
)
|
97
|
+
|
98
|
+
response_key_ttl: int = Field(
|
99
|
+
default=60,
|
100
|
+
ge=10,
|
101
|
+
le=3600,
|
102
|
+
description="Response key TTL (seconds) for auto-cleanup",
|
103
|
+
)
|
104
|
+
|
105
|
+
# Performance settings
|
106
|
+
enable_connection_pooling: bool = Field(
|
107
|
+
default=True,
|
108
|
+
description="Enable Redis connection pooling",
|
109
|
+
)
|
110
|
+
|
111
|
+
socket_keepalive: bool = Field(
|
112
|
+
default=True,
|
113
|
+
description="Enable TCP keepalive for Redis connections",
|
114
|
+
)
|
115
|
+
|
116
|
+
# Logging settings
|
117
|
+
log_rpc_calls: bool = Field(
|
118
|
+
default=False,
|
119
|
+
description="Log all RPC calls (verbose, use for debugging)",
|
120
|
+
)
|
121
|
+
|
122
|
+
log_level: str = Field(
|
123
|
+
default="INFO",
|
124
|
+
pattern=r"^(DEBUG|INFO|WARNING|ERROR|CRITICAL)$",
|
125
|
+
description="Log level for RPC module",
|
126
|
+
)
|
127
|
+
|
128
|
+
@field_validator("redis_url")
|
129
|
+
@classmethod
|
130
|
+
def validate_redis_url(cls, v: str) -> str:
|
131
|
+
"""
|
132
|
+
Validate Redis URL format.
|
133
|
+
|
134
|
+
Args:
|
135
|
+
v: Redis URL to validate
|
136
|
+
|
137
|
+
Returns:
|
138
|
+
Validated Redis URL
|
139
|
+
|
140
|
+
Raises:
|
141
|
+
ValueError: If URL format is invalid
|
142
|
+
"""
|
143
|
+
if not v.startswith("redis://") and not v.startswith("rediss://"):
|
144
|
+
raise ValueError(
|
145
|
+
"redis_url must start with 'redis://' or 'rediss://' "
|
146
|
+
f"(got: {v})"
|
147
|
+
)
|
148
|
+
|
149
|
+
return v
|
150
|
+
|
151
|
+
def to_django_settings(self) -> dict:
|
152
|
+
"""
|
153
|
+
Generate Django settings dictionary.
|
154
|
+
|
155
|
+
Returns:
|
156
|
+
Dictionary with DJANGO_CFG_RPC settings
|
157
|
+
|
158
|
+
Example:
|
159
|
+
>>> config = DjangoCfgRPCConfig(enabled=True)
|
160
|
+
>>> settings_dict = config.to_django_settings()
|
161
|
+
>>> print(settings_dict["DJANGO_CFG_RPC"]["REDIS_URL"])
|
162
|
+
"""
|
163
|
+
if not self.enabled:
|
164
|
+
return {}
|
165
|
+
|
166
|
+
return {
|
167
|
+
"DJANGO_CFG_RPC": {
|
168
|
+
"ENABLED": self.enabled,
|
169
|
+
"REDIS_URL": self.redis_url,
|
170
|
+
"REDIS_MAX_CONNECTIONS": self.redis_max_connections,
|
171
|
+
"RPC_TIMEOUT": self.rpc_timeout,
|
172
|
+
"REQUEST_STREAM": self.request_stream,
|
173
|
+
"CONSUMER_GROUP": self.consumer_group,
|
174
|
+
"STREAM_MAXLEN": self.stream_maxlen,
|
175
|
+
"RESPONSE_KEY_PREFIX": self.response_key_prefix,
|
176
|
+
"RESPONSE_KEY_TTL": self.response_key_ttl,
|
177
|
+
"LOG_RPC_CALLS": self.log_rpc_calls,
|
178
|
+
"LOG_LEVEL": self.log_level,
|
179
|
+
}
|
180
|
+
}
|
181
|
+
|
182
|
+
def get_redis_config(self) -> dict:
|
183
|
+
"""
|
184
|
+
Get Redis connection configuration.
|
185
|
+
|
186
|
+
Returns:
|
187
|
+
Dictionary with Redis connection options
|
188
|
+
|
189
|
+
Example:
|
190
|
+
>>> config = DjangoCfgRPCConfig()
|
191
|
+
>>> redis_config = config.get_redis_config()
|
192
|
+
>>> import redis
|
193
|
+
>>> redis_client = redis.Redis.from_url(**redis_config)
|
194
|
+
"""
|
195
|
+
config = {
|
196
|
+
"url": self.redis_url,
|
197
|
+
"max_connections": self.redis_max_connections,
|
198
|
+
"decode_responses": False, # We handle JSON ourselves
|
199
|
+
}
|
200
|
+
|
201
|
+
if self.socket_keepalive:
|
202
|
+
config["socket_keepalive"] = True
|
203
|
+
|
204
|
+
return config
|
205
|
+
|
206
|
+
|
207
|
+
__all__ = ["DjangoCfgRPCConfig"]
|
@@ -0,0 +1,517 @@
|
|
1
|
+
# RPC Dashboard 📊
|
2
|
+
|
3
|
+
**Real-time WebSocket & RPC Activity Monitor**
|
4
|
+
|
5
|
+
Built-in dashboard for monitoring RPC requests, notifications, and WebSocket activity.
|
6
|
+
|
7
|
+
---
|
8
|
+
|
9
|
+
## ✨ Features
|
10
|
+
|
11
|
+
- ✅ **Real-time Monitoring** - Live updates every 5 seconds
|
12
|
+
- ✅ **Request Tracking** - View recent RPC calls with details
|
13
|
+
- ✅ **Notification Stats** - Track sent notifications by type
|
14
|
+
- ✅ **Method Analytics** - See which RPC methods are called most
|
15
|
+
- ✅ **Health Checks** - Monitor Redis and stream status
|
16
|
+
- ✅ **Tailwind CSS** - Beautiful dark mode UI
|
17
|
+
- ✅ **Zero Config** - Works out of the box
|
18
|
+
- ✅ **Django Cache** - 3-second cache reduces Redis load
|
19
|
+
- ✅ **XSS Protection** - Secure against injection attacks
|
20
|
+
- ✅ **Stream Validation** - Whitelist prevents Redis key injection
|
21
|
+
- ✅ **Error Handling** - Specific HTTP codes (400, 503, 500)
|
22
|
+
|
23
|
+
---
|
24
|
+
|
25
|
+
## 🚀 Quick Start
|
26
|
+
|
27
|
+
### ✨ Automatic Integration (Recommended)
|
28
|
+
|
29
|
+
Simply enable RPC in your django-cfg configuration:
|
30
|
+
|
31
|
+
```python
|
32
|
+
# config.py
|
33
|
+
from django_cfg import DjangoConfig
|
34
|
+
from django_cfg.modules.django_ipc_client.config import DjangoCfgRPCConfig
|
35
|
+
|
36
|
+
class MyProjectConfig(DjangoConfig):
|
37
|
+
# Enable RPC Client
|
38
|
+
django_ipc = DjangoCfgRPCConfig(
|
39
|
+
enabled=True,
|
40
|
+
redis_url="redis://localhost:6379/2",
|
41
|
+
)
|
42
|
+
|
43
|
+
config = MyProjectConfig()
|
44
|
+
```
|
45
|
+
|
46
|
+
**That's it!** Django-cfg automatically:
|
47
|
+
- ✅ Adds dashboard app to `INSTALLED_APPS`
|
48
|
+
- ✅ Registers URL at `/admin/rpc/`
|
49
|
+
- ✅ Adds "Operations" section to Unfold navigation
|
50
|
+
- ✅ Generates `DJANGO_CFG_RPC` settings
|
51
|
+
|
52
|
+
### Access Dashboard
|
53
|
+
|
54
|
+
Navigate to: **http://localhost:8000/admin/rpc/**
|
55
|
+
|
56
|
+
(Requires staff user login - `is_staff=True`)
|
57
|
+
|
58
|
+
---
|
59
|
+
|
60
|
+
### Manual Integration (Advanced)
|
61
|
+
|
62
|
+
If not using django-cfg's automatic integration:
|
63
|
+
|
64
|
+
```python
|
65
|
+
# urls.py
|
66
|
+
from django.urls import path, include
|
67
|
+
|
68
|
+
urlpatterns = [
|
69
|
+
# RPC Dashboard (requires staff login)
|
70
|
+
path('admin/rpc/', include('django_cfg.modules.django_ipc_client.dashboard.urls')),
|
71
|
+
]
|
72
|
+
```
|
73
|
+
|
74
|
+
For Unfold navigation customization, see [UNFOLD_INTEGRATION.md](./UNFOLD_INTEGRATION.md)
|
75
|
+
|
76
|
+
---
|
77
|
+
|
78
|
+
## 📊 Dashboard Tabs
|
79
|
+
|
80
|
+
### Overview Tab
|
81
|
+
|
82
|
+
Shows key metrics:
|
83
|
+
- Total requests today
|
84
|
+
- Active RPC methods
|
85
|
+
- Average response time
|
86
|
+
- Success rate
|
87
|
+
|
88
|
+
### Recent Requests Tab
|
89
|
+
|
90
|
+
Live stream of RPC calls:
|
91
|
+
- Timestamp
|
92
|
+
- Method name
|
93
|
+
- Correlation ID
|
94
|
+
- Request parameters (expandable)
|
95
|
+
|
96
|
+
### Notifications Tab
|
97
|
+
|
98
|
+
Notification statistics:
|
99
|
+
- Total sent
|
100
|
+
- Delivery rate
|
101
|
+
- Breakdown by type
|
102
|
+
- Recent notifications
|
103
|
+
|
104
|
+
### Methods Tab
|
105
|
+
|
106
|
+
Analytics by RPC method:
|
107
|
+
- Call count
|
108
|
+
- Percentage of total
|
109
|
+
- Average response time
|
110
|
+
|
111
|
+
---
|
112
|
+
|
113
|
+
## 🔧 Configuration
|
114
|
+
|
115
|
+
### Default Settings
|
116
|
+
|
117
|
+
```python
|
118
|
+
# In your Django settings.py (auto-configured)
|
119
|
+
DJANGO_CFG_RPC = {
|
120
|
+
'redis_url': 'redis://localhost:6379/2', # RPC database
|
121
|
+
'request_stream': 'stream:requests',
|
122
|
+
# ... other settings
|
123
|
+
}
|
124
|
+
```
|
125
|
+
|
126
|
+
### URL Customization
|
127
|
+
|
128
|
+
Mount at custom path:
|
129
|
+
|
130
|
+
```python
|
131
|
+
urlpatterns = [
|
132
|
+
path('my/custom/path/', include('django_cfg.modules.django_ipc_client.dashboard.urls')),
|
133
|
+
]
|
134
|
+
```
|
135
|
+
|
136
|
+
---
|
137
|
+
|
138
|
+
## 🧪 Testing
|
139
|
+
|
140
|
+
### Run Tests
|
141
|
+
|
142
|
+
```bash
|
143
|
+
# Run all dashboard tests
|
144
|
+
pytest django_cfg/modules/django_ipc_client/tests/
|
145
|
+
|
146
|
+
# Run monitor tests
|
147
|
+
pytest django_cfg/modules/django_ipc_client/tests/test_monitor.py -v
|
148
|
+
|
149
|
+
# Run view tests
|
150
|
+
pytest django_cfg/modules/django_ipc_client/tests/test_dashboard.py -v
|
151
|
+
```
|
152
|
+
|
153
|
+
### Test Coverage
|
154
|
+
|
155
|
+
- ✅ **RPCMonitor**: 15 tests
|
156
|
+
- ✅ **Dashboard Views**: 10 tests
|
157
|
+
- ✅ **Integration Tests**: Fakeredis support
|
158
|
+
|
159
|
+
---
|
160
|
+
|
161
|
+
## 📡 API Endpoints
|
162
|
+
|
163
|
+
Dashboard exposes JSON API endpoints:
|
164
|
+
|
165
|
+
| Endpoint | Method | Description |
|
166
|
+
|----------|--------|-------------|
|
167
|
+
| `/admin/rpc/api/overview/` | GET | Overview statistics |
|
168
|
+
| `/admin/rpc/api/requests/?count=50` | GET | Recent RPC requests |
|
169
|
+
| `/admin/rpc/api/notifications/` | GET | Notification stats |
|
170
|
+
| `/admin/rpc/api/methods/` | GET | Method statistics |
|
171
|
+
| `/admin/rpc/api/health/` | GET | Health check |
|
172
|
+
|
173
|
+
All endpoints return JSON:
|
174
|
+
|
175
|
+
```json
|
176
|
+
{
|
177
|
+
"success": true,
|
178
|
+
"data": { ... }
|
179
|
+
}
|
180
|
+
```
|
181
|
+
|
182
|
+
---
|
183
|
+
|
184
|
+
## 🏗️ Architecture
|
185
|
+
|
186
|
+
```
|
187
|
+
dashboard/
|
188
|
+
├── monitor.py # RPCMonitor class (reads Redis)
|
189
|
+
├── views.py # Django views + JSON API
|
190
|
+
├── urls.py # URL routing
|
191
|
+
├── templates/ # Tailwind CSS templates
|
192
|
+
│ └── django_ipc_dashboard/
|
193
|
+
│ ├── base.html
|
194
|
+
│ └── dashboard.html
|
195
|
+
└── static/ # JavaScript
|
196
|
+
└── django_ipc_dashboard/
|
197
|
+
└── js/
|
198
|
+
└── dashboard.js
|
199
|
+
```
|
200
|
+
|
201
|
+
### Data Flow
|
202
|
+
|
203
|
+
```
|
204
|
+
Redis DB 2 (stream:requests)
|
205
|
+
↓
|
206
|
+
RPCMonitor.get_overview_stats()
|
207
|
+
↓
|
208
|
+
Django View (dashboard_view)
|
209
|
+
↓
|
210
|
+
Template (dashboard.html)
|
211
|
+
↓
|
212
|
+
JavaScript (auto-refresh every 5s)
|
213
|
+
↓
|
214
|
+
API Endpoints (/api/overview/, etc.)
|
215
|
+
```
|
216
|
+
|
217
|
+
---
|
218
|
+
|
219
|
+
## 🎨 Customization
|
220
|
+
|
221
|
+
### Disable Auto-Refresh
|
222
|
+
|
223
|
+
Toggle "Auto-refresh" checkbox in dashboard header.
|
224
|
+
|
225
|
+
### Change Refresh Interval
|
226
|
+
|
227
|
+
Edit `dashboard.js`:
|
228
|
+
|
229
|
+
```javascript
|
230
|
+
class RPCDashboard {
|
231
|
+
constructor() {
|
232
|
+
this.refreshInterval = 10000; // 10 seconds instead of 5
|
233
|
+
// ...
|
234
|
+
}
|
235
|
+
}
|
236
|
+
```
|
237
|
+
|
238
|
+
### Custom Styling
|
239
|
+
|
240
|
+
Override Tailwind classes or add custom CSS to `base.html`.
|
241
|
+
|
242
|
+
---
|
243
|
+
|
244
|
+
## 🐛 Troubleshooting
|
245
|
+
|
246
|
+
### Dashboard shows "Redis not connected"
|
247
|
+
|
248
|
+
**Check:**
|
249
|
+
1. Redis running: `redis-cli ping`
|
250
|
+
2. Correct Redis URL in config
|
251
|
+
3. Using DB 2 for RPC: `redis://localhost:6379/2`
|
252
|
+
|
253
|
+
**Solution:**
|
254
|
+
```bash
|
255
|
+
# Check Redis is running
|
256
|
+
redis-cli -h localhost -p 6379 ping # Should return "PONG"
|
257
|
+
|
258
|
+
# Check database 2 is accessible
|
259
|
+
redis-cli -h localhost -p 6379 -n 2 ping
|
260
|
+
```
|
261
|
+
|
262
|
+
### No requests showing up
|
263
|
+
|
264
|
+
**Check:**
|
265
|
+
1. RPC client actually making requests
|
266
|
+
2. Request stream exists: `redis-cli XLEN stream:requests`
|
267
|
+
3. Recent activity (last 5 minutes)
|
268
|
+
|
269
|
+
**Debug:**
|
270
|
+
```bash
|
271
|
+
# Check stream exists and has data
|
272
|
+
redis-cli -n 2 XLEN stream:requests
|
273
|
+
|
274
|
+
# View latest request
|
275
|
+
redis-cli -n 2 XREVRANGE stream:requests + - COUNT 1
|
276
|
+
```
|
277
|
+
|
278
|
+
### Permission denied
|
279
|
+
|
280
|
+
**Solution:** Dashboard requires staff user login (`is_staff=True`)
|
281
|
+
|
282
|
+
```python
|
283
|
+
user = User.objects.get(username='your_user')
|
284
|
+
user.is_staff = True
|
285
|
+
user.save()
|
286
|
+
```
|
287
|
+
|
288
|
+
### Dashboard is slow / High Redis load
|
289
|
+
|
290
|
+
**Solution:** Dashboard uses 3-second cache. If still slow:
|
291
|
+
|
292
|
+
1. Increase cache timeout in `monitor.py`:
|
293
|
+
```python
|
294
|
+
CACHE_TIMEOUT = 5 # Change from 3 to 5 seconds
|
295
|
+
```
|
296
|
+
|
297
|
+
2. Configure Django cache backend (default uses in-memory):
|
298
|
+
```python
|
299
|
+
# settings.py
|
300
|
+
CACHES = {
|
301
|
+
'default': {
|
302
|
+
'BACKEND': 'django.core.cache.backends.redis.RedisCache',
|
303
|
+
'LOCATION': 'redis://localhost:6379/0',
|
304
|
+
}
|
305
|
+
}
|
306
|
+
```
|
307
|
+
|
308
|
+
3. Reduce stream read count in `monitor.py`:
|
309
|
+
```python
|
310
|
+
recent_requests = self._get_recent_stream_entries(count=500) # Down from 1000
|
311
|
+
```
|
312
|
+
|
313
|
+
### API returns 503 "Service Unavailable"
|
314
|
+
|
315
|
+
**Cause:** Redis connection lost or timeout
|
316
|
+
|
317
|
+
**Solution:**
|
318
|
+
```python
|
319
|
+
# Check Redis connection settings
|
320
|
+
config = DjangoCfgRPCConfig()
|
321
|
+
print(config.redis_url) # Should be redis://localhost:6379/2
|
322
|
+
|
323
|
+
# Increase timeout in monitor.py _create_redis_client():
|
324
|
+
client = redis.Redis(
|
325
|
+
socket_connect_timeout=10, # Up from 5
|
326
|
+
socket_timeout=10, # Up from 5
|
327
|
+
)
|
328
|
+
|
329
|
+
---
|
330
|
+
|
331
|
+
## 📚 Related Documentation
|
332
|
+
|
333
|
+
- [RPC Client README](../README.md)
|
334
|
+
- [RPC Integration Guide](../../../../../../@docs/websocket2/RPC_DRAMATIQ_INTEGRATION.md)
|
335
|
+
- [Redis Database Allocation](../../../../../../@docs/websocket2/REDIS_DATABASES.md)
|
336
|
+
|
337
|
+
---
|
338
|
+
|
339
|
+
## 🎯 Example Use Cases
|
340
|
+
|
341
|
+
### 1. Monitor Notification Delivery
|
342
|
+
|
343
|
+
Track how many notifications are sent to users:
|
344
|
+
|
345
|
+
1. Go to "Notifications" tab
|
346
|
+
2. See total sent + delivery rate
|
347
|
+
3. Breakdown by notification type
|
348
|
+
|
349
|
+
### 2. Debug RPC Issues
|
350
|
+
|
351
|
+
When RPC calls fail:
|
352
|
+
|
353
|
+
1. Go to "Recent Requests" tab
|
354
|
+
2. Find failing request
|
355
|
+
3. Expand "View" to see parameters
|
356
|
+
4. Check correlation ID for tracing
|
357
|
+
|
358
|
+
### 3. Analyze Performance
|
359
|
+
|
360
|
+
Find slow RPC methods:
|
361
|
+
|
362
|
+
1. Go to "Methods" tab
|
363
|
+
2. Sort by "Avg Time"
|
364
|
+
3. Identify bottlenecks
|
365
|
+
|
366
|
+
---
|
367
|
+
|
368
|
+
## ✅ Summary
|
369
|
+
|
370
|
+
- **Location**: `django_cfg/modules/django_ipc_client/dashboard/`
|
371
|
+
- **URL**: `/admin/rpc/` (customizable)
|
372
|
+
- **Requirements**: Staff login, Redis DB 2
|
373
|
+
- **Tech Stack**: Django, Tailwind CSS, Vanilla JS
|
374
|
+
- **Tests**: 25+ tests with mocks + fakeredis
|
375
|
+
|
376
|
+
**Production Ready**: ✅
|
377
|
+
|
378
|
+
---
|
379
|
+
|
380
|
+
## 🚀 Production Deployment Checklist
|
381
|
+
|
382
|
+
### 1. Security
|
383
|
+
- [ ] Verify all views use `@staff_member_required`
|
384
|
+
- [ ] Configure HTTPS for dashboard URL
|
385
|
+
- [ ] Enable CSRF protection (Django default)
|
386
|
+
- [ ] Set strong `SECRET_KEY` in production
|
387
|
+
|
388
|
+
### 2. Redis Configuration
|
389
|
+
- [ ] Use dedicated Redis DB for RPC (DB 2)
|
390
|
+
- [ ] Configure Redis persistence (AOF or RDB)
|
391
|
+
- [ ] Set Redis `maxmemory-policy` to `allkeys-lru`
|
392
|
+
- [ ] Enable Redis password authentication
|
393
|
+
|
394
|
+
```python
|
395
|
+
# Production config
|
396
|
+
DJANGO_CFG_RPC = DjangoCfgRPCConfig(
|
397
|
+
redis_url="redis://:strong_password@redis-server:6379/2",
|
398
|
+
redis_max_connections=100, # Increase for production
|
399
|
+
)
|
400
|
+
```
|
401
|
+
|
402
|
+
### 3. Django Cache
|
403
|
+
- [ ] Configure Redis cache backend (not in-memory)
|
404
|
+
- [ ] Set cache timeout appropriately
|
405
|
+
|
406
|
+
```python
|
407
|
+
# settings.py
|
408
|
+
CACHES = {
|
409
|
+
'default': {
|
410
|
+
'BACKEND': 'django.core.cache.backends.redis.RedisCache',
|
411
|
+
'LOCATION': 'redis://localhost:6379/0',
|
412
|
+
'OPTIONS': {
|
413
|
+
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
|
414
|
+
}
|
415
|
+
}
|
416
|
+
}
|
417
|
+
```
|
418
|
+
|
419
|
+
### 4. Static Files
|
420
|
+
- [ ] Run `python manage.py collectstatic`
|
421
|
+
- [ ] Configure static files serving (nginx/whitenoise)
|
422
|
+
- [ ] Verify Tailwind CSS loads from CDN
|
423
|
+
|
424
|
+
### 5. Performance
|
425
|
+
- [ ] Monitor Redis memory usage
|
426
|
+
- [ ] Set stream MAXLEN to prevent unbounded growth
|
427
|
+
- [ ] Consider Redis eviction policy
|
428
|
+
- [ ] Enable connection pooling (default: enabled)
|
429
|
+
|
430
|
+
```bash
|
431
|
+
# Monitor Redis memory
|
432
|
+
redis-cli INFO memory
|
433
|
+
|
434
|
+
# Trim old stream entries (if needed)
|
435
|
+
redis-cli -n 2 XTRIM stream:requests MAXLEN 10000
|
436
|
+
```
|
437
|
+
|
438
|
+
### 6. Monitoring
|
439
|
+
- [ ] Set up logging for dashboard errors
|
440
|
+
- [ ] Monitor API endpoint response times
|
441
|
+
- [ ] Track Redis connection errors
|
442
|
+
- [ ] Set up alerts for 503 errors
|
443
|
+
|
444
|
+
```python
|
445
|
+
# settings.py - Enhanced logging
|
446
|
+
LOGGING = {
|
447
|
+
'loggers': {
|
448
|
+
'django_cfg.modules.django_ipc_client.dashboard': {
|
449
|
+
'level': 'INFO',
|
450
|
+
'handlers': ['file', 'sentry'], # Add Sentry for production
|
451
|
+
},
|
452
|
+
},
|
453
|
+
}
|
454
|
+
```
|
455
|
+
|
456
|
+
### 7. Testing
|
457
|
+
- [ ] Run all tests: `pytest django_cfg/modules/django_ipc_client/tests/`
|
458
|
+
- [ ] Load test API endpoints
|
459
|
+
- [ ] Verify dashboard loads with production data
|
460
|
+
- [ ] Test with Redis connection failures
|
461
|
+
|
462
|
+
### 8. Documentation
|
463
|
+
- [ ] Document custom URL mounting path
|
464
|
+
- [ ] Document Redis DB allocation
|
465
|
+
- [ ] Document staff user creation process
|
466
|
+
|
467
|
+
---
|
468
|
+
|
469
|
+
## 🔧 Performance Optimization
|
470
|
+
|
471
|
+
### Redis Stream Management
|
472
|
+
|
473
|
+
Prevent unlimited stream growth:
|
474
|
+
|
475
|
+
```bash
|
476
|
+
# Add to cron (daily cleanup)
|
477
|
+
redis-cli -n 2 XTRIM stream:requests MAXLEN 50000
|
478
|
+
|
479
|
+
# Or use MAXLEN in stream writes (django-cfg-rpc server)
|
480
|
+
XADD stream:requests MAXLEN ~ 10000 * payload {...}
|
481
|
+
```
|
482
|
+
|
483
|
+
### Cache Configuration
|
484
|
+
|
485
|
+
Optimize cache for high traffic:
|
486
|
+
|
487
|
+
```python
|
488
|
+
# monitor.py - Adjust cache timeout based on traffic
|
489
|
+
CACHE_TIMEOUT = 5 # Higher for production (less Redis load)
|
490
|
+
|
491
|
+
# settings.py - Use connection pool
|
492
|
+
CACHES = {
|
493
|
+
'default': {
|
494
|
+
'LOCATION': 'redis://localhost:6379/0',
|
495
|
+
'OPTIONS': {
|
496
|
+
'CONNECTION_POOL_KWARGS': {
|
497
|
+
'max_connections': 50
|
498
|
+
}
|
499
|
+
}
|
500
|
+
}
|
501
|
+
}
|
502
|
+
```
|
503
|
+
|
504
|
+
---
|
505
|
+
|
506
|
+
## 🔒 Security Notes
|
507
|
+
|
508
|
+
1. **XSS Protection**: All user data sanitized via `textContent` (not `innerHTML`)
|
509
|
+
2. **Stream Key Validation**: Whitelist prevents Redis key injection
|
510
|
+
3. **Staff-Only Access**: All endpoints require `is_staff=True`
|
511
|
+
4. **Error Messages**: Generic messages in production (no stack traces to clients)
|
512
|
+
5. **CSRF**: Django CSRF protection enabled by default
|
513
|
+
|
514
|
+
---
|
515
|
+
|
516
|
+
**Last Updated**: 2025-10-03
|
517
|
+
**Version**: 2.0 (Security Hardened)
|