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,75 @@
|
|
1
|
+
"""
|
2
|
+
Smart defaults for ExternalData configuration.
|
3
|
+
|
4
|
+
Provides sensible defaults for ExternalData configuration when not explicitly specified.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from typing import List
|
8
|
+
|
9
|
+
from ...models.external_data import ExternalDataType
|
10
|
+
from ..generators import ExternalDataFieldAnalyzer
|
11
|
+
|
12
|
+
|
13
|
+
class ExternalDataDefaults:
|
14
|
+
"""
|
15
|
+
Provide smart defaults for ExternalData configuration.
|
16
|
+
|
17
|
+
Offers utilities to get sensible defaults when ExternalDataMeta
|
18
|
+
is not provided or incomplete.
|
19
|
+
"""
|
20
|
+
|
21
|
+
@staticmethod
|
22
|
+
def get_default_watch_fields(model_class) -> List[str]:
|
23
|
+
"""
|
24
|
+
Get default watch fields for a model class.
|
25
|
+
|
26
|
+
Uses field analyzer to detect important fields.
|
27
|
+
|
28
|
+
Args:
|
29
|
+
model_class: Django model class
|
30
|
+
|
31
|
+
Returns:
|
32
|
+
List of field names to watch
|
33
|
+
"""
|
34
|
+
analyzer = ExternalDataFieldAnalyzer(model_class)
|
35
|
+
return analyzer.auto_detect_watch_fields()
|
36
|
+
|
37
|
+
@staticmethod
|
38
|
+
def get_default_source_type() -> ExternalDataType:
|
39
|
+
"""
|
40
|
+
Get default source type.
|
41
|
+
|
42
|
+
Returns:
|
43
|
+
ExternalDataType.MODEL as default
|
44
|
+
"""
|
45
|
+
return ExternalDataType.MODEL
|
46
|
+
|
47
|
+
@staticmethod
|
48
|
+
def get_default_similarity_threshold() -> float:
|
49
|
+
"""
|
50
|
+
Get default similarity threshold.
|
51
|
+
|
52
|
+
Returns:
|
53
|
+
0.5 as balanced default threshold
|
54
|
+
"""
|
55
|
+
return 0.5
|
56
|
+
|
57
|
+
@staticmethod
|
58
|
+
def get_default_auto_sync() -> bool:
|
59
|
+
"""
|
60
|
+
Get default auto_sync setting.
|
61
|
+
|
62
|
+
Returns:
|
63
|
+
True (enabled by default)
|
64
|
+
"""
|
65
|
+
return True
|
66
|
+
|
67
|
+
@staticmethod
|
68
|
+
def get_default_is_public() -> bool:
|
69
|
+
"""
|
70
|
+
Get default is_public setting.
|
71
|
+
|
72
|
+
Returns:
|
73
|
+
False (private by default for security)
|
74
|
+
"""
|
75
|
+
return False
|
@@ -0,0 +1,120 @@
|
|
1
|
+
"""
|
2
|
+
ExternalDataMeta configuration parser.
|
3
|
+
|
4
|
+
Handles parsing and processing of ExternalDataMeta configuration from model classes.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from dataclasses import dataclass, field
|
8
|
+
from typing import List, Dict, Any
|
9
|
+
|
10
|
+
from ...models.external_data import ExternalDataType
|
11
|
+
from ..generators import ExternalDataFieldAnalyzer
|
12
|
+
|
13
|
+
|
14
|
+
@dataclass
|
15
|
+
class ExternalDataMetaConfig:
|
16
|
+
"""
|
17
|
+
Configuration from ExternalDataMeta class.
|
18
|
+
|
19
|
+
Attributes:
|
20
|
+
watch_fields: List of field names to watch for changes
|
21
|
+
similarity_threshold: Threshold for similarity search (0.0-1.0)
|
22
|
+
source_type: Type of external data source
|
23
|
+
auto_sync: Whether to automatically sync on changes
|
24
|
+
is_public: Whether data is public
|
25
|
+
title: Title for the external data (for create_from_config)
|
26
|
+
description: Description for the external data
|
27
|
+
content: Content for the external data
|
28
|
+
source_identifier: Source identifier
|
29
|
+
is_active: Whether the data is active
|
30
|
+
metadata: Additional metadata
|
31
|
+
tags: List of tags
|
32
|
+
source_config: Source configuration dict
|
33
|
+
"""
|
34
|
+
# Core configuration fields
|
35
|
+
watch_fields: List[str] = field(default_factory=list)
|
36
|
+
similarity_threshold: float = 0.5
|
37
|
+
source_type: ExternalDataType = ExternalDataType.MODEL
|
38
|
+
auto_sync: bool = True
|
39
|
+
is_public: bool = False
|
40
|
+
|
41
|
+
# ExternalData creation fields (used by ExternalDataCreator)
|
42
|
+
title: str = ""
|
43
|
+
description: str = ""
|
44
|
+
content: str = ""
|
45
|
+
source_identifier: str = ""
|
46
|
+
is_active: bool = True
|
47
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
48
|
+
tags: List[str] = field(default_factory=list)
|
49
|
+
source_config: Dict[str, Any] = field(default_factory=dict)
|
50
|
+
|
51
|
+
|
52
|
+
class ExternalDataMetaParser:
|
53
|
+
"""
|
54
|
+
Parse ExternalDataMeta from model class.
|
55
|
+
|
56
|
+
Extracts configuration from model's ExternalDataMeta inner class
|
57
|
+
and applies smart defaults where needed.
|
58
|
+
"""
|
59
|
+
|
60
|
+
@staticmethod
|
61
|
+
def parse(model_class) -> Dict[str, Any]:
|
62
|
+
"""
|
63
|
+
Parse ExternalDataMeta configuration from model class.
|
64
|
+
|
65
|
+
Args:
|
66
|
+
model_class: Django model class with optional ExternalDataMeta
|
67
|
+
|
68
|
+
Returns:
|
69
|
+
Dictionary with parsed configuration and smart defaults
|
70
|
+
"""
|
71
|
+
config = {}
|
72
|
+
|
73
|
+
# If ExternalDataMeta exists, use it
|
74
|
+
if hasattr(model_class, 'ExternalDataMeta'):
|
75
|
+
meta_class = model_class.ExternalDataMeta
|
76
|
+
# Extract configuration from ExternalDataMeta
|
77
|
+
for attr in dir(meta_class):
|
78
|
+
if not attr.startswith('_'):
|
79
|
+
value = getattr(meta_class, attr)
|
80
|
+
if not callable(value): # Only properties, not methods
|
81
|
+
config[attr] = value
|
82
|
+
|
83
|
+
# Smart defaults based on model analysis
|
84
|
+
if 'watch_fields' not in config:
|
85
|
+
analyzer = ExternalDataFieldAnalyzer(model_class)
|
86
|
+
config['watch_fields'] = analyzer.auto_detect_watch_fields()
|
87
|
+
|
88
|
+
if 'similarity_threshold' not in config:
|
89
|
+
config['similarity_threshold'] = 0.5 # Balanced default
|
90
|
+
|
91
|
+
if 'source_type' not in config:
|
92
|
+
config['source_type'] = ExternalDataType.MODEL # Smart default
|
93
|
+
|
94
|
+
if 'auto_sync' not in config:
|
95
|
+
config['auto_sync'] = True # Enable by default
|
96
|
+
|
97
|
+
if 'is_public' not in config:
|
98
|
+
config['is_public'] = False # Private by default for security
|
99
|
+
|
100
|
+
return config
|
101
|
+
|
102
|
+
@staticmethod
|
103
|
+
def to_dataclass(model_class) -> ExternalDataMetaConfig:
|
104
|
+
"""
|
105
|
+
Parse configuration and return as dataclass.
|
106
|
+
|
107
|
+
Args:
|
108
|
+
model_class: Django model class
|
109
|
+
|
110
|
+
Returns:
|
111
|
+
ExternalDataMetaConfig dataclass instance
|
112
|
+
"""
|
113
|
+
config_dict = ExternalDataMetaParser.parse(model_class)
|
114
|
+
return ExternalDataMetaConfig(
|
115
|
+
watch_fields=config_dict.get('watch_fields', []),
|
116
|
+
similarity_threshold=config_dict.get('similarity_threshold', 0.5),
|
117
|
+
source_type=config_dict.get('source_type', ExternalDataType.MODEL),
|
118
|
+
auto_sync=config_dict.get('auto_sync', True),
|
119
|
+
is_public=config_dict.get('is_public', False),
|
120
|
+
)
|
@@ -8,7 +8,7 @@ from django.contrib.auth import get_user_model
|
|
8
8
|
from django.db import transaction
|
9
9
|
from django.utils import timezone
|
10
10
|
|
11
|
-
from .config import
|
11
|
+
from .config import ExternalDataMetaConfig
|
12
12
|
from ..models.external_data import ExternalData, ExternalDataStatus
|
13
13
|
|
14
14
|
logger = logging.getLogger(__name__)
|
@@ -25,12 +25,12 @@ class ExternalDataCreator:
|
|
25
25
|
else:
|
26
26
|
self.user = user
|
27
27
|
|
28
|
-
def create_from_config(self, config:
|
28
|
+
def create_from_config(self, config: ExternalDataMetaConfig) -> Dict[str, Any]:
|
29
29
|
"""
|
30
30
|
Create an ExternalData object from a Pydantic configuration.
|
31
31
|
|
32
32
|
Args:
|
33
|
-
config: An instance of
|
33
|
+
config: An instance of ExternalDataMetaConfig.
|
34
34
|
|
35
35
|
Returns:
|
36
36
|
dict: Result with success status, external_data object, and message/error.
|
@@ -72,10 +72,10 @@ class ExternalDataCreator:
|
|
72
72
|
def _get_default_user(self):
|
73
73
|
"""Get default user for ExternalData ownership."""
|
74
74
|
User = get_user_model()
|
75
|
-
|
76
|
-
# Try to find a superuser
|
77
|
-
|
78
|
-
if
|
79
|
-
return
|
80
|
-
|
81
|
-
raise ValueError("No user provided and no
|
75
|
+
|
76
|
+
# Try to find a staff user (staff or superuser)
|
77
|
+
staff_user = User.objects.filter(is_staff=True).first()
|
78
|
+
if staff_user:
|
79
|
+
return staff_user
|
80
|
+
|
81
|
+
raise ValueError("No user provided and no staff user found for ExternalData ownership")
|
@@ -0,0 +1,199 @@
|
|
1
|
+
"""
|
2
|
+
Example of using ExternalDataMixin with VehicleModel.
|
3
|
+
|
4
|
+
This shows how to integrate VehicleModel with knowbase using the mixin.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from django.db import models
|
8
|
+
from django_cfg.apps.knowbase.mixins import ExternalDataMixin
|
9
|
+
from django_cfg.apps.knowbase.models.external_data import ExternalDataType
|
10
|
+
|
11
|
+
|
12
|
+
class VehicleModelWithMixin(ExternalDataMixin, models.Model):
|
13
|
+
"""
|
14
|
+
Example VehicleModel with ExternalDataMixin integration.
|
15
|
+
|
16
|
+
This replaces the manual integration we had before with automatic
|
17
|
+
tracking and vectorization.
|
18
|
+
"""
|
19
|
+
|
20
|
+
# Original VehicleModel fields
|
21
|
+
brand = models.ForeignKey('vehicles_data.Brand', on_delete=models.CASCADE)
|
22
|
+
code = models.CharField(max_length=20)
|
23
|
+
name = models.CharField(max_length=100)
|
24
|
+
body_type = models.CharField(max_length=20, blank=True)
|
25
|
+
segment = models.CharField(max_length=50, blank=True)
|
26
|
+
is_active = models.BooleanField(default=True)
|
27
|
+
total_vehicles = models.PositiveIntegerField(default=0)
|
28
|
+
created_at = models.DateTimeField(auto_now_add=True)
|
29
|
+
updated_at = models.DateTimeField(auto_now=True)
|
30
|
+
|
31
|
+
class Meta:
|
32
|
+
abstract = True # This is just an example
|
33
|
+
|
34
|
+
class ExternalDataMeta:
|
35
|
+
# Fields to watch for changes - only update when these change
|
36
|
+
watch_fields = ['name', 'body_type', 'segment', 'is_active']
|
37
|
+
|
38
|
+
# Lower threshold for multilingual vehicle data
|
39
|
+
similarity_threshold = 0.4
|
40
|
+
|
41
|
+
# Vehicle models are model type
|
42
|
+
source_type = ExternalDataType.MODEL
|
43
|
+
|
44
|
+
# Enable auto-sync
|
45
|
+
auto_sync = True
|
46
|
+
|
47
|
+
# Make public for search
|
48
|
+
is_public = True
|
49
|
+
|
50
|
+
# Required: content generation method
|
51
|
+
def get_external_content(self):
|
52
|
+
"""Generate content for vectorization."""
|
53
|
+
content_parts = [
|
54
|
+
f"# {self.brand.name} {self.name}",
|
55
|
+
"",
|
56
|
+
"## Basic Information",
|
57
|
+
f"- **Brand**: {self.brand.name} ({self.brand.code})",
|
58
|
+
f"- **Model**: {self.name} ({self.code})",
|
59
|
+
]
|
60
|
+
|
61
|
+
if self.body_type:
|
62
|
+
content_parts.append(f"- **Body Type**: {self.body_type}")
|
63
|
+
|
64
|
+
if self.segment:
|
65
|
+
content_parts.append(f"- **Market Segment**: {self.segment}")
|
66
|
+
|
67
|
+
content_parts.extend([
|
68
|
+
f"- **Status**: {'Active' if self.is_active else 'Inactive'}",
|
69
|
+
"",
|
70
|
+
"## Market Statistics",
|
71
|
+
f"- **Total Listings**: {self.total_vehicles:,} vehicles available",
|
72
|
+
])
|
73
|
+
|
74
|
+
if hasattr(self, 'vehicles') and self.vehicles.exists():
|
75
|
+
# Add some vehicle statistics if available
|
76
|
+
vehicles = self.vehicles.filter(is_active=True)
|
77
|
+
if vehicles.exists():
|
78
|
+
content_parts.extend([
|
79
|
+
"",
|
80
|
+
"## Available Vehicles",
|
81
|
+
f"- **Active Listings**: {vehicles.count():,} vehicles",
|
82
|
+
])
|
83
|
+
|
84
|
+
# Add price range if available
|
85
|
+
if hasattr(vehicles.first(), 'price'):
|
86
|
+
prices = vehicles.exclude(price__isnull=True).values_list('price', flat=True)
|
87
|
+
if prices:
|
88
|
+
min_price = min(prices)
|
89
|
+
max_price = max(prices)
|
90
|
+
content_parts.append(f"- **Price Range**: ${min_price:,} - ${max_price:,}")
|
91
|
+
|
92
|
+
content_parts.extend([
|
93
|
+
"",
|
94
|
+
f"## Model History",
|
95
|
+
f"- **First Listed**: {self.created_at.strftime('%Y-%m-%d')}",
|
96
|
+
f"- **Last Updated**: {self.updated_at.strftime('%Y-%m-%d')}",
|
97
|
+
])
|
98
|
+
|
99
|
+
return "\n".join(content_parts)
|
100
|
+
|
101
|
+
# Optional: custom title
|
102
|
+
def get_external_title(self):
|
103
|
+
"""Generate title for ExternalData."""
|
104
|
+
return f"Vehicle Model: {self.brand.name} {self.name}"
|
105
|
+
|
106
|
+
# Optional: custom description
|
107
|
+
def get_external_description(self):
|
108
|
+
"""Generate description for ExternalData."""
|
109
|
+
parts = [f"Comprehensive information about {self.brand.name} {self.name}"]
|
110
|
+
|
111
|
+
if self.body_type:
|
112
|
+
parts.append(f"({self.body_type})")
|
113
|
+
|
114
|
+
parts.append("including specifications, market data, and vehicle listings.")
|
115
|
+
|
116
|
+
return " ".join(parts)
|
117
|
+
|
118
|
+
# Optional: metadata
|
119
|
+
def get_external_metadata(self):
|
120
|
+
"""Generate metadata for ExternalData."""
|
121
|
+
return {
|
122
|
+
'vehicle_model_id': str(self.id),
|
123
|
+
'brand_code': self.brand.code,
|
124
|
+
'brand_name': self.brand.name,
|
125
|
+
'model_code': self.code,
|
126
|
+
'model_name': self.name,
|
127
|
+
'body_type': self.body_type,
|
128
|
+
'segment': self.segment,
|
129
|
+
'total_vehicles': self.total_vehicles,
|
130
|
+
'is_active': self.is_active,
|
131
|
+
'created_at': self.created_at.isoformat(),
|
132
|
+
'updated_at': self.updated_at.isoformat(),
|
133
|
+
'integration_type': 'vehicle_model_mixin_auto'
|
134
|
+
}
|
135
|
+
|
136
|
+
# Optional: tags
|
137
|
+
def get_external_tags(self):
|
138
|
+
"""Generate tags for ExternalData."""
|
139
|
+
tags = [
|
140
|
+
'vehicle',
|
141
|
+
'model',
|
142
|
+
self.brand.code.lower(),
|
143
|
+
self.code.lower(),
|
144
|
+
self.brand.name.lower().replace(' ', '_'),
|
145
|
+
self.name.lower().replace(' ', '_'),
|
146
|
+
]
|
147
|
+
|
148
|
+
if self.body_type:
|
149
|
+
tags.append(self.body_type.lower().replace(' ', '_'))
|
150
|
+
|
151
|
+
if self.segment:
|
152
|
+
tags.append(self.segment.lower().replace(' ', '_'))
|
153
|
+
|
154
|
+
return tags
|
155
|
+
|
156
|
+
@property
|
157
|
+
def full_name(self):
|
158
|
+
"""Get full model name with brand."""
|
159
|
+
return f"{self.brand.name} {self.name}"
|
160
|
+
|
161
|
+
def __str__(self):
|
162
|
+
return self.full_name
|
163
|
+
|
164
|
+
|
165
|
+
# Usage example:
|
166
|
+
"""
|
167
|
+
# To use this mixin in your existing VehicleModel:
|
168
|
+
|
169
|
+
1. Add the mixin to your model:
|
170
|
+
class VehicleModel(ExternalDataMixin, models.Model):
|
171
|
+
# ... your existing fields ...
|
172
|
+
|
173
|
+
class ExternalDataMeta:
|
174
|
+
watch_fields = ['name', 'body_type', 'segment', 'is_active']
|
175
|
+
similarity_threshold = 0.4
|
176
|
+
source_type = ExternalDataType.MODEL
|
177
|
+
auto_sync = True
|
178
|
+
is_public = True
|
179
|
+
|
180
|
+
def get_external_content(self):
|
181
|
+
# ... content generation logic ...
|
182
|
+
return content
|
183
|
+
|
184
|
+
2. Run migrations to add the mixin fields:
|
185
|
+
python manage.py makemigrations
|
186
|
+
python manage.py migrate
|
187
|
+
|
188
|
+
3. That's it! The mixin will automatically:
|
189
|
+
- Create ExternalData when VehicleModel is created
|
190
|
+
- Update ExternalData when watched fields change
|
191
|
+
- Delete ExternalData when VehicleModel is deleted
|
192
|
+
- Handle vectorization and search integration
|
193
|
+
|
194
|
+
4. Manual operations (if needed):
|
195
|
+
vehicle_model.regenerate_external_data() # Force regeneration
|
196
|
+
vehicle_model.delete_external_data() # Remove integration
|
197
|
+
vehicle_model.has_external_data # Check if linked
|
198
|
+
vehicle_model.external_data_status # Get processing status
|
199
|
+
"""
|