django-cfg 1.3.11__py3-none-any.whl → 1.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- django_cfg/__init__.py +1 -1
- django_cfg/apps/accounts/admin/inlines.py +11 -5
- django_cfg/apps/accounts/admin/user_admin.py +39 -16
- django_cfg/apps/accounts/serializers/profile.py +1 -1
- django_cfg/apps/accounts/services/otp_service.py +18 -11
- django_cfg/apps/accounts/signals.py +15 -24
- django_cfg/apps/accounts/utils/notifications.py +217 -358
- django_cfg/apps/accounts/views/otp.py +2 -2
- django_cfg/apps/accounts/views/webhook.py +1 -1
- django_cfg/apps/agents/core/django_agent.py +1 -1
- django_cfg/apps/api/commands/views.py +66 -83
- django_cfg/apps/api/health/drf_views.py +269 -0
- django_cfg/apps/api/health/serializers.py +45 -0
- django_cfg/apps/api/health/urls.py +6 -1
- django_cfg/apps/knowbase/admin/actions/__init__.py +13 -0
- django_cfg/apps/knowbase/admin/actions/visibility_actions.py +56 -0
- django_cfg/apps/knowbase/admin/document_admin.py +136 -270
- django_cfg/apps/knowbase/admin/helpers/__init__.py +17 -0
- django_cfg/apps/knowbase/admin/helpers/configs.py +72 -0
- django_cfg/apps/knowbase/admin/helpers/display_helpers.py +156 -0
- django_cfg/apps/knowbase/admin/helpers/statistics.py +108 -0
- django_cfg/apps/knowbase/config/constance_fields.py +1 -1
- django_cfg/apps/knowbase/config/settings.py +2 -2
- django_cfg/apps/knowbase/mixins/__init__.py +19 -2
- django_cfg/apps/knowbase/mixins/config/__init__.py +14 -0
- django_cfg/apps/knowbase/mixins/config/defaults.py +75 -0
- django_cfg/apps/knowbase/mixins/config/meta_config.py +120 -0
- django_cfg/apps/knowbase/mixins/creator.py +10 -10
- django_cfg/apps/knowbase/mixins/external_data_mixin.py +105 -403
- django_cfg/apps/knowbase/mixins/generators/__init__.py +16 -0
- django_cfg/apps/knowbase/mixins/generators/content_generator.py +218 -0
- django_cfg/apps/knowbase/mixins/generators/field_analyzer.py +76 -0
- django_cfg/apps/knowbase/mixins/generators/metadata_generator.py +124 -0
- django_cfg/apps/knowbase/mixins/service.py +2 -2
- django_cfg/apps/knowbase/services/archive/__init__.py +1 -0
- django_cfg/apps/knowbase/services/archive/analyzers/__init__.py +17 -0
- django_cfg/apps/knowbase/services/archive/analyzers/complexity_analyzer.py +33 -0
- django_cfg/apps/knowbase/services/archive/analyzers/purpose_detector.py +36 -0
- django_cfg/apps/knowbase/services/archive/analyzers/quality_analyzer.py +39 -0
- django_cfg/apps/knowbase/services/archive/analyzers/tag_generator.py +103 -0
- django_cfg/apps/knowbase/services/archive/chunking/__init__.py +19 -0
- django_cfg/apps/knowbase/services/archive/chunking/base.py +81 -0
- django_cfg/apps/knowbase/services/archive/chunking/json_chunker.py +62 -0
- django_cfg/apps/knowbase/services/archive/chunking/markdown_chunker.py +107 -0
- django_cfg/apps/knowbase/services/archive/chunking/python_chunker.py +248 -0
- django_cfg/apps/knowbase/services/archive/chunking/text_chunker.py +70 -0
- django_cfg/apps/knowbase/services/archive/chunking_service.py +110 -729
- django_cfg/apps/knowbase/services/archive/context/__init__.py +14 -0
- django_cfg/apps/knowbase/services/archive/context/builders.py +220 -0
- django_cfg/apps/knowbase/services/archive/context/models.py +38 -0
- django_cfg/apps/knowbase/services/embedding/models.py +18 -14
- django_cfg/apps/knowbase/services/embedding/processors.py +6 -3
- django_cfg/apps/knowbase/tasks/document_processing.py +11 -3
- django_cfg/apps/leads/tests.py +1 -1
- django_cfg/apps/payments/admin/api_keys_admin.py +1 -1
- django_cfg/apps/payments/admin/balance_admin.py +1 -1
- django_cfg/apps/payments/admin/currencies_admin.py +1 -1
- django_cfg/apps/payments/admin/payments_admin.py +1 -1
- django_cfg/apps/payments/admin/subscriptions_admin.py +1 -1
- django_cfg/apps/payments/admin_interface/templates/payments/base.html +59 -126
- django_cfg/apps/payments/admin_interface/views/api/payments.py +1 -1
- django_cfg/apps/payments/admin_interface/views/api/stats.py +1 -1
- django_cfg/apps/payments/admin_interface/views/api/users.py +1 -1
- django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +1 -1
- django_cfg/apps/payments/admin_interface/views/api/webhook_public.py +1 -1
- django_cfg/apps/payments/admin_interface/views/base.py +29 -2
- django_cfg/apps/payments/apps.py +1 -1
- django_cfg/apps/payments/config/django_cfg_integration.py +2 -2
- django_cfg/apps/payments/config/helpers.py +3 -2
- django_cfg/apps/payments/management/commands/cleanup_expired_data.py +1 -1
- django_cfg/apps/payments/management/commands/currency_stats.py +1 -1
- django_cfg/apps/payments/management/commands/manage_currencies.py +1 -1
- django_cfg/apps/payments/management/commands/manage_providers.py +1 -1
- django_cfg/apps/payments/management/commands/process_pending_payments.py +1 -1
- django_cfg/apps/payments/management/commands/test_providers.py +1 -1
- django_cfg/apps/payments/middleware/api_access.py +1 -1
- django_cfg/apps/payments/middleware/rate_limiting.py +1 -1
- django_cfg/apps/payments/middleware/usage_tracking.py +1 -1
- django_cfg/apps/payments/models/balance.py +2 -2
- django_cfg/apps/payments/models/managers/api_key_managers.py +1 -1
- django_cfg/apps/payments/models/managers/balance_managers.py +1 -1
- django_cfg/apps/payments/models/managers/currency_managers.py +1 -1
- django_cfg/apps/payments/models/managers/payment_managers.py +1 -1
- django_cfg/apps/payments/models/managers/subscription_managers.py +1 -1
- django_cfg/apps/payments/models/payments.py +2 -2
- django_cfg/apps/payments/services/cache_service/__init__.py +1 -1
- django_cfg/apps/payments/services/cache_service/simple_cache.py +10 -5
- django_cfg/apps/payments/services/core/base.py +1 -1
- django_cfg/apps/payments/services/core/currency/__init__.py +13 -0
- django_cfg/apps/payments/services/core/currency/currency_converter.py +57 -0
- django_cfg/apps/payments/services/core/currency/currency_validator.py +61 -0
- django_cfg/apps/payments/services/core/operations/__init__.py +15 -0
- django_cfg/apps/payments/services/core/operations/payment_canceller.py +100 -0
- django_cfg/apps/payments/services/core/operations/payment_creator.py +196 -0
- django_cfg/apps/payments/services/core/operations/status_checker.py +100 -0
- django_cfg/apps/payments/services/core/payment_service.py +124 -612
- django_cfg/apps/payments/services/core/providers/__init__.py +13 -0
- django_cfg/apps/payments/services/core/providers/provider_client.py +132 -0
- django_cfg/apps/payments/services/core/providers/status_mapper.py +89 -0
- django_cfg/apps/payments/services/core/utils/__init__.py +13 -0
- django_cfg/apps/payments/services/core/utils/data_converter.py +48 -0
- django_cfg/apps/payments/services/core/utils/statistics_calculator.py +69 -0
- django_cfg/apps/payments/services/providers/base.py +1 -1
- django_cfg/apps/payments/services/providers/nowpayments/__init__.py +3 -3
- django_cfg/apps/payments/services/providers/nowpayments/parsers/__init__.py +9 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/__init__.py +23 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/constants.py +23 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/currency_names.py +244 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/patterns.py +511 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/parser.py +168 -0
- django_cfg/apps/payments/services/providers/nowpayments/provider.py +1 -1
- django_cfg/apps/payments/services/providers/nowpayments/sync.py +1 -1
- django_cfg/apps/payments/services/providers/registry.py +1 -1
- django_cfg/apps/payments/services/providers/sync_service.py +1 -1
- django_cfg/apps/payments/signals/__init__.py +1 -1
- django_cfg/apps/payments/signals/api_key_signals.py +1 -1
- django_cfg/apps/payments/signals/balance_signals.py +1 -1
- django_cfg/apps/payments/signals/payment_signals.py +1 -1
- django_cfg/apps/payments/signals/subscription_signals.py +1 -1
- django_cfg/apps/payments/views/api/api_keys.py +1 -1
- django_cfg/apps/payments/views/api/balances.py +1 -1
- django_cfg/apps/payments/views/api/base.py +1 -1
- django_cfg/apps/payments/views/api/currencies.py +1 -1
- django_cfg/apps/payments/views/api/payments.py +1 -1
- django_cfg/apps/payments/views/api/subscriptions.py +1 -1
- django_cfg/apps/payments/views/api/webhooks.py +1 -1
- django_cfg/apps/payments/views/serializers/api_keys.py +1 -1
- django_cfg/apps/payments/views/serializers/balances.py +1 -1
- django_cfg/apps/payments/views/serializers/currencies.py +1 -1
- django_cfg/apps/payments/views/serializers/payments.py +1 -1
- django_cfg/apps/payments/views/serializers/subscriptions.py +1 -1
- django_cfg/apps/payments/views/serializers/webhooks.py +1 -1
- django_cfg/apps/support/admin/support_admin.py +21 -13
- django_cfg/apps/support/templates/support/chat/access_denied.html +21 -27
- django_cfg/apps/support/templates/support/chat/ticket_chat.html +183 -254
- django_cfg/apps/support/utils/support_email_service.py +1 -1
- django_cfg/apps/tasks/templates/tasks/layout/base.html +20 -115
- django_cfg/apps/tasks/utils/simulator.py +1 -1
- django_cfg/apps/tasks/views/dashboard.py +33 -3
- django_cfg/apps/urls.py +5 -1
- django_cfg/cli/README.md +57 -471
- django_cfg/cli/commands/create_project.py +140 -529
- django_cfg/cli/main.py +13 -10
- django_cfg/core/__init__.py +63 -6
- django_cfg/core/base/__init__.py +5 -0
- django_cfg/core/base/config_model.py +652 -0
- django_cfg/core/builders/__init__.py +11 -0
- django_cfg/core/builders/apps_builder.py +258 -0
- django_cfg/core/builders/middleware_builder.py +115 -0
- django_cfg/core/builders/security_builder.py +96 -0
- django_cfg/core/config.py +20 -892
- django_cfg/core/constants.py +69 -0
- django_cfg/core/environment/__init__.py +9 -0
- django_cfg/core/exceptions.py +45 -298
- django_cfg/core/generation/__init__.py +51 -0
- django_cfg/core/generation/core_generators/__init__.py +0 -0
- django_cfg/core/generation/core_generators/settings.py +90 -0
- django_cfg/core/generation/core_generators/static.py +82 -0
- django_cfg/core/generation/core_generators/templates.py +141 -0
- django_cfg/core/generation/data_generators/__init__.py +15 -0
- django_cfg/core/generation/data_generators/cache.py +132 -0
- django_cfg/core/generation/data_generators/database.py +117 -0
- django_cfg/core/generation/generation.py +92 -0
- django_cfg/core/generation/integration_generators/__init__.py +21 -0
- django_cfg/core/generation/integration_generators/api.py +237 -0
- django_cfg/core/generation/integration_generators/sessions.py +65 -0
- django_cfg/core/generation/integration_generators/tailwind.py +54 -0
- django_cfg/core/generation/integration_generators/tasks.py +92 -0
- django_cfg/core/generation/integration_generators/third_party.py +144 -0
- django_cfg/core/generation/orchestrator.py +285 -0
- django_cfg/core/generation/protocols.py +30 -0
- django_cfg/core/generation/security_generators/__init__.py +0 -0
- django_cfg/core/generation/utility_generators/__init__.py +24 -0
- django_cfg/core/generation/utility_generators/email.py +58 -0
- django_cfg/core/generation/utility_generators/i18n.py +66 -0
- django_cfg/core/generation/utility_generators/limits.py +58 -0
- django_cfg/core/generation/utility_generators/logging.py +66 -0
- django_cfg/core/generation/utility_generators/security.py +101 -0
- django_cfg/core/generation/utils/__init__.py +0 -0
- django_cfg/core/generation/utils/helpers.py +32 -0
- django_cfg/core/integration/__init__.py +18 -25
- django_cfg/core/integration/display/startup.py +146 -133
- django_cfg/core/integration/url_integration.py +13 -2
- django_cfg/core/services/__init__.py +5 -0
- django_cfg/core/services/config_service.py +121 -0
- django_cfg/core/state/__init__.py +9 -0
- django_cfg/core/state/registry.py +84 -0
- django_cfg/core/types/__init__.py +15 -0
- django_cfg/core/types/aliases.py +15 -0
- django_cfg/core/types/enums.py +49 -0
- django_cfg/dashboard/DEBUG_README.md +105 -0
- django_cfg/dashboard/REFACTORING_SUMMARY.md +237 -0
- django_cfg/dashboard/__init__.py +24 -0
- django_cfg/dashboard/components.py +308 -0
- django_cfg/dashboard/debug.py +176 -0
- django_cfg/dashboard/management/__init__.py +0 -0
- django_cfg/dashboard/management/commands/__init__.py +0 -0
- django_cfg/dashboard/management/commands/debug_dashboard.py +109 -0
- django_cfg/dashboard/sections/__init__.py +1 -0
- django_cfg/dashboard/sections/base.py +128 -0
- django_cfg/dashboard/sections/commands.py +32 -0
- django_cfg/dashboard/sections/overview.py +394 -0
- django_cfg/dashboard/sections/stats.py +48 -0
- django_cfg/dashboard/sections/system.py +73 -0
- django_cfg/management/commands/check_settings.py +6 -2
- django_cfg/management/commands/clear_constance.py +6 -1
- django_cfg/management/commands/create_token.py +5 -4
- django_cfg/management/commands/generate.py +5 -0
- django_cfg/management/commands/list_urls.py +7 -2
- django_cfg/management/commands/migrate_all.py +6 -2
- django_cfg/management/commands/migrator.py +6 -1
- django_cfg/management/commands/rundramatiq.py +6 -1
- django_cfg/management/commands/rundramatiq_simulator.py +11 -4
- django_cfg/management/commands/runserver_ngrok.py +9 -7
- django_cfg/management/commands/script.py +25 -21
- django_cfg/management/commands/show_config.py +6 -1
- django_cfg/management/commands/show_urls.py +8 -3
- django_cfg/management/commands/superuser.py +5 -4
- django_cfg/management/commands/task_clear.py +8 -3
- django_cfg/management/commands/task_status.py +8 -3
- django_cfg/management/commands/test_email.py +6 -1
- django_cfg/management/commands/test_telegram.py +6 -1
- django_cfg/management/commands/test_twilio.py +6 -1
- django_cfg/management/commands/tree.py +7 -4
- django_cfg/models/__init__.py +88 -3
- django_cfg/models/api/__init__.py +27 -0
- django_cfg/models/{api.py → api/config.py} +1 -1
- django_cfg/models/api/drf/__init__.py +21 -0
- django_cfg/models/api/drf/config.py +101 -0
- django_cfg/models/api/drf/redoc.py +31 -0
- django_cfg/models/api/drf/spectacular.py +129 -0
- django_cfg/models/api/drf/swagger.py +59 -0
- django_cfg/models/{api_keys.py → api/keys.py} +16 -6
- django_cfg/models/{limits.py → api/limits.py} +0 -1
- django_cfg/models/base/__init__.py +14 -0
- django_cfg/models/django/__init__.py +16 -0
- django_cfg/models/{constance.py → django/constance.py} +1 -1
- django_cfg/models/{environment.py → django/environment.py} +1 -1
- django_cfg/models/infrastructure/__init__.py +17 -0
- django_cfg/models/{cache.py → infrastructure/cache.py} +3 -2
- django_cfg/models/infrastructure/database/__init__.py +22 -0
- django_cfg/models/infrastructure/database/config.py +265 -0
- django_cfg/models/infrastructure/database/converters.py +91 -0
- django_cfg/models/infrastructure/database/parsers.py +96 -0
- django_cfg/models/infrastructure/database/routing.py +85 -0
- django_cfg/models/infrastructure/database/validators.py +170 -0
- django_cfg/models/{logging.py → infrastructure/logging.py} +1 -1
- django_cfg/models/{security.py → infrastructure/security.py} +2 -2
- django_cfg/models/ngrok/__init__.py +11 -0
- django_cfg/models/ngrok/auth.py +37 -0
- django_cfg/models/ngrok/config.py +77 -0
- django_cfg/models/ngrok/tunnel.py +35 -0
- django_cfg/models/payments/__init__.py +20 -0
- django_cfg/models/payments/api_keys.py +57 -0
- django_cfg/models/{payments.py → payments/config.py} +56 -154
- django_cfg/models/payments/providers/__init__.py +15 -0
- django_cfg/models/payments/providers/base.py +25 -0
- django_cfg/models/payments/providers/nowpayments.py +48 -0
- django_cfg/models/services/__init__.py +18 -0
- django_cfg/models/services/base.py +65 -0
- django_cfg/models/{email.py → services/email.py} +1 -1
- django_cfg/models/services/telegram.py +172 -0
- django_cfg/models/tasks/__init__.py +51 -0
- django_cfg/models/tasks/backends.py +250 -0
- django_cfg/models/tasks/config.py +314 -0
- django_cfg/models/tasks/utils.py +174 -0
- django_cfg/modules/base.py +18 -3
- django_cfg/modules/django_admin/decorators/actions.py +1 -1
- django_cfg/modules/django_admin/decorators/display.py +1 -1
- django_cfg/modules/django_admin/mixins/standalone_actions_mixin.py +1 -1
- django_cfg/modules/django_cfg_rpc_client/README.md +346 -0
- django_cfg/modules/django_cfg_rpc_client/__init__.py +51 -0
- django_cfg/modules/django_cfg_rpc_client/client.py +540 -0
- django_cfg/modules/django_cfg_rpc_client/config.py +207 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/README.md +517 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/UNFOLD_INTEGRATION.md +439 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/__init__.py +11 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/apps.py +22 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/monitor.py +435 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/static/django_cfg_rpc_dashboard/js/dashboard.js +373 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/templates/django_cfg_rpc_dashboard/base.html +76 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/templates/django_cfg_rpc_dashboard/dashboard.html +200 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/urls.py +22 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/urls_admin.py +9 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/views.py +251 -0
- django_cfg/modules/django_cfg_rpc_client/exceptions.py +201 -0
- django_cfg/modules/django_drf_theme/CHANGELOG.md +210 -0
- django_cfg/modules/django_drf_theme/EXAMPLE.md +465 -0
- django_cfg/modules/django_drf_theme/IMPLEMENTATION.md +232 -0
- django_cfg/modules/django_drf_theme/README.md +207 -0
- django_cfg/modules/django_drf_theme/TAILWIND_CDN_GUIDE.md +274 -0
- django_cfg/modules/django_drf_theme/__init__.py +23 -0
- django_cfg/modules/django_drf_theme/apps.py +15 -0
- django_cfg/modules/django_drf_theme/renderers.py +58 -0
- django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/api.html +375 -0
- django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/base.html +938 -0
- django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/forms/filter_form.html +132 -0
- django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/forms/raw_data_form.html +123 -0
- django_cfg/modules/django_drf_theme/templatetags/__init__.py +1 -0
- django_cfg/modules/django_drf_theme/templatetags/tailwind_tags.py +57 -0
- django_cfg/modules/django_email/__init__.py +14 -0
- django_cfg/modules/{django_email.py → django_email/service.py} +78 -113
- django_cfg/modules/django_email/utils.py +40 -0
- django_cfg/modules/django_health/__init__.py +9 -0
- django_cfg/modules/{django_health.py → django_health/service.py} +23 -21
- django_cfg/modules/django_llm/llm/client.py +155 -550
- django_cfg/modules/django_llm/llm/embeddings/__init__.py +13 -0
- django_cfg/modules/django_llm/llm/embeddings/mock_embedder.py +106 -0
- django_cfg/modules/django_llm/llm/embeddings/openai_embedder.py +79 -0
- django_cfg/modules/django_llm/llm/models_api/__init__.py +9 -0
- django_cfg/modules/django_llm/llm/models_api/models_query.py +163 -0
- django_cfg/modules/django_llm/llm/providers/__init__.py +15 -0
- django_cfg/modules/django_llm/llm/providers/config_builder.py +103 -0
- django_cfg/modules/django_llm/llm/providers/provider_manager.py +148 -0
- django_cfg/modules/django_llm/llm/providers/provider_selector.py +60 -0
- django_cfg/modules/django_llm/llm/requests/__init__.py +15 -0
- django_cfg/modules/django_llm/llm/requests/cache_manager.py +170 -0
- django_cfg/modules/django_llm/llm/requests/chat_handler.py +199 -0
- django_cfg/modules/django_llm/llm/requests/embedding_handler.py +113 -0
- django_cfg/modules/django_llm/llm/responses/__init__.py +9 -0
- django_cfg/modules/django_llm/llm/responses/response_builder.py +131 -0
- django_cfg/modules/django_llm/llm/stats/__init__.py +9 -0
- django_cfg/modules/django_llm/llm/stats/stats_manager.py +107 -0
- django_cfg/modules/django_llm/translator/detectors/__init__.py +13 -0
- django_cfg/modules/django_llm/translator/detectors/language_detector.py +90 -0
- django_cfg/modules/django_llm/translator/detectors/script_detector.py +153 -0
- django_cfg/modules/django_llm/translator/stats/__init__.py +11 -0
- django_cfg/modules/django_llm/translator/stats/stats_tracker.py +85 -0
- django_cfg/modules/django_llm/translator/translator.py +150 -603
- django_cfg/modules/django_llm/translator/translators/__init__.py +15 -0
- django_cfg/modules/django_llm/translator/translators/json_translator.py +316 -0
- django_cfg/modules/django_llm/translator/translators/text_translator.py +139 -0
- django_cfg/modules/django_llm/translator/utils/__init__.py +13 -0
- django_cfg/modules/django_llm/translator/utils/prompt_builder.py +110 -0
- django_cfg/modules/django_llm/translator/utils/text_utils.py +114 -0
- django_cfg/modules/django_logging/FIXES_SUMMARY.md +276 -0
- django_cfg/modules/django_logging/LOGGING_GUIDE.md +504 -0
- django_cfg/modules/django_logging/__init__.py +14 -0
- django_cfg/modules/{django_logger.py → django_logging/django_logger.py} +13 -13
- django_cfg/modules/{logger.py → django_logging/logger.py} +14 -4
- django_cfg/modules/django_ngrok/__init__.py +39 -0
- django_cfg/modules/{django_ngrok.py → django_ngrok/service.py} +14 -42
- django_cfg/modules/django_rpc_old/POETRY.md +344 -0
- django_cfg/modules/django_rpc_old/README.md +397 -0
- django_cfg/modules/django_rpc_old/TESTING.md +358 -0
- django_cfg/modules/django_rpc_old/__init__.py +39 -0
- django_cfg/modules/django_rpc_old/client.py +531 -0
- django_cfg/modules/django_rpc_old/config.py +279 -0
- django_cfg/modules/django_rpc_old/exceptions.py +172 -0
- django_cfg/modules/django_tailwind/README.md +478 -0
- django_cfg/modules/django_tailwind/__init__.py +7 -0
- django_cfg/modules/django_tailwind/apps.py +10 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/app.html +5 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/base.html +117 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/components/navbar.html +124 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/components/theme_toggle.html +54 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/components/user_menu.html +116 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/simple.html +46 -0
- django_cfg/modules/django_tailwind/templatetags/__init__.py +1 -0
- django_cfg/modules/django_tailwind/templatetags/tailwind_info.py +185 -0
- django_cfg/modules/django_tasks/__init__.py +29 -0
- django_cfg/modules/django_tasks/factory.py +127 -0
- django_cfg/modules/{django_tasks.py → django_tasks/service.py} +45 -274
- django_cfg/modules/django_tasks/settings.py +107 -0
- django_cfg/modules/django_telegram/__init__.py +29 -0
- django_cfg/modules/{django_telegram.py → django_telegram/service.py} +45 -113
- django_cfg/modules/django_telegram/utils.py +62 -0
- django_cfg/modules/django_twilio/__init__.py +54 -107
- django_cfg/modules/django_twilio/_imports.py +30 -0
- django_cfg/modules/django_twilio/base.py +192 -0
- django_cfg/modules/django_twilio/email_otp.py +227 -0
- django_cfg/modules/django_twilio/sendgrid_service.py +1 -1
- django_cfg/modules/django_twilio/simple_service.py +1 -2
- django_cfg/modules/django_twilio/sms.py +94 -0
- django_cfg/modules/django_twilio/twilio_service.py +2 -3
- django_cfg/modules/django_twilio/unified.py +310 -0
- django_cfg/modules/django_twilio/utils.py +190 -0
- django_cfg/modules/django_twilio/whatsapp.py +137 -0
- django_cfg/modules/django_unfold/callbacks/base.py +198 -7
- django_cfg/modules/django_unfold/callbacks/main.py +102 -10
- django_cfg/modules/django_unfold/dashboard.py +65 -43
- django_cfg/modules/django_unfold/models/config.py +13 -12
- django_cfg/modules/django_unfold/models/navigation.py +8 -3
- django_cfg/modules/django_unfold/models/tabs.py +2 -2
- django_cfg/modules/django_unfold/templates/unfold/helpers/app_list.html +102 -0
- django_cfg/registry/core.py +24 -26
- django_cfg/registry/modules.py +5 -2
- django_cfg/registry/services.py +20 -3
- django_cfg/registry/third_party.py +8 -8
- django_cfg/static/admin/css/dashboard.css +260 -0
- django_cfg/static/admin/js/commands.js +171 -0
- django_cfg/static/admin/js/dashboard.js +126 -0
- django_cfg/templates/admin/components/management_commands.js +375 -0
- django_cfg/templates/admin/components/progress_bar.html +18 -23
- django_cfg/templates/admin/index.html +48 -20
- django_cfg/templates/admin/index_new.html +106 -0
- django_cfg/templates/admin/layouts/base_dashboard.html +60 -0
- django_cfg/templates/admin/layouts/dashboard_with_tabs.html +1 -20
- django_cfg/templates/admin/sections/commands_section.html +626 -0
- django_cfg/templates/admin/sections/overview_section.html +112 -0
- django_cfg/templates/admin/sections/stats_section.html +35 -0
- django_cfg/templates/admin/sections/system_section.html +99 -0
- django_cfg/templates/admin/snippets/components/CHARTS_GUIDE.md +322 -0
- django_cfg/templates/admin/snippets/components/activity_tracker.html +85 -47
- django_cfg/templates/admin/snippets/components/charts_section.html +154 -64
- django_cfg/templates/admin/snippets/components/django_commands.html +3 -3
- django_cfg/templates/admin/snippets/components/recent_activity_improved.html +25 -0
- django_cfg/templates/admin/snippets/components/recent_users_table.html +1 -1
- django_cfg/templates/admin/snippets/components/system_metrics.html +179 -93
- django_cfg/templates/admin/snippets/zones/zones_table.html +2 -2
- django_cfg/templatetags/django_cfg.py +7 -1
- django_cfg/utils/smart_defaults.py +4 -4
- django_cfg-1.4.0.dist-info/METADATA +920 -0
- {django_cfg-1.3.11.dist-info → django_cfg-1.4.0.dist-info}/RECORD +425 -196
- django_cfg/apps/accounts/utils/auth_email_service.py +0 -84
- django_cfg/apps/payments/services/providers/nowpayments/parsers.py +0 -879
- django_cfg/core/generation.py +0 -621
- django_cfg/management/commands/validate_config.py +0 -189
- django_cfg/models/database.py +0 -480
- django_cfg/models/drf.py +0 -272
- django_cfg/models/ngrok.py +0 -122
- django_cfg/models/services.py +0 -440
- django_cfg/models/tasks.py +0 -550
- django_cfg/modules/django_twilio/service.py +0 -942
- django_cfg/template_archive/django_sample.zip +0 -0
- django_cfg/templates/rest_framework/api.html +0 -12
- django_cfg/utils/toolkit.py +0 -703
- django_cfg-1.3.11.dist-info/METADATA +0 -1029
- /django_cfg/apps/accounts/management/commands/{test_otp.py → otp_test.py} +0 -0
- /django_cfg/core/{environment.py → environment/detector.py} +0 -0
- /django_cfg/models/{cors.py → api/cors.py} +0 -0
- /django_cfg/models/{jwt.py → api/jwt.py} +0 -0
- /django_cfg/models/{base.py → base/config.py} +0 -0
- /django_cfg/models/{cfg.py → base/module.py} +0 -0
- /django_cfg/models/{revolution.py → django/revolution.py} +0 -0
- /django_cfg/modules/{dramatiq_setup.py → django_tasks/dramatiq_setup.py} +0 -0
- {django_cfg-1.3.11.dist-info → django_cfg-1.4.0.dist-info}/WHEEL +0 -0
- {django_cfg-1.3.11.dist-info → django_cfg-1.4.0.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.3.11.dist-info → django_cfg-1.4.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,395 +1,116 @@
|
|
1
1
|
"""
|
2
2
|
Django CFG Create Project Command
|
3
3
|
|
4
|
-
Creates a new Django project
|
4
|
+
Creates a new Django project by downloading from GitHub.
|
5
5
|
"""
|
6
6
|
|
7
7
|
import click
|
8
8
|
import shutil
|
9
|
-
import
|
9
|
+
import urllib.request
|
10
10
|
from pathlib import Path
|
11
|
-
from typing import Optional
|
12
11
|
import tempfile
|
13
|
-
import
|
14
|
-
import sys
|
15
|
-
from rich.console import Console
|
16
|
-
from rich.panel import Panel
|
17
|
-
from rich.text import Text
|
18
|
-
|
19
|
-
from ..utils import find_template_archive, validate_project_name
|
20
|
-
|
21
|
-
console = Console()
|
22
|
-
|
23
|
-
|
24
|
-
def show_thank_you_message():
|
25
|
-
"""Display a beautiful thank you message with company info."""
|
26
|
-
# Create styled text
|
27
|
-
title = Text("Thank you for using django-cfg!", style="bold cyan")
|
28
|
-
|
29
|
-
# Company info with clickable link
|
30
|
-
company_text = Text()
|
31
|
-
company_text.append("Developed by ", style="white")
|
32
|
-
company_text.append("Unrealon.com", style="bold blue underline")
|
33
|
-
company_text.append(" — Complex parsers on demand", style="white")
|
34
|
-
|
35
|
-
link_text = Text()
|
36
|
-
link_text.append("🌐 ", style="green")
|
37
|
-
link_text.append("https://unrealon.com", style="blue underline")
|
38
|
-
|
39
|
-
# Create panel content
|
40
|
-
panel_content = Text()
|
41
|
-
panel_content.append(title)
|
42
|
-
panel_content.append("\n\n")
|
43
|
-
panel_content.append(company_text)
|
44
|
-
panel_text = Text()
|
45
|
-
panel_text.append("\n")
|
46
|
-
panel_text.append(link_text)
|
47
|
-
panel_content.append(panel_text)
|
48
|
-
|
49
|
-
# Display beautiful panel
|
50
|
-
console.print()
|
51
|
-
console.print(Panel(
|
52
|
-
panel_content,
|
53
|
-
title="🚀 Django CFG",
|
54
|
-
title_align="center",
|
55
|
-
border_style="bright_blue",
|
56
|
-
padding=(1, 2)
|
57
|
-
))
|
58
|
-
|
59
|
-
|
60
|
-
def extract_template(archive_path: Path, target_path: Path, project_name: str) -> None:
|
61
|
-
"""Extract template archive to target directory with project name replacements."""
|
62
|
-
import zipfile
|
63
|
-
|
64
|
-
click.echo(f"📂 Extracting template from archive...")
|
65
|
-
|
66
|
-
target_path = Path(target_path)
|
67
|
-
target_path.mkdir(parents=True, exist_ok=True)
|
68
|
-
|
69
|
-
files_extracted = 0
|
70
|
-
try:
|
71
|
-
with zipfile.ZipFile(archive_path, 'r') as archive:
|
72
|
-
for member in archive.namelist():
|
73
|
-
# Extract file
|
74
|
-
archive.extract(member, target_path)
|
75
|
-
files_extracted += 1
|
76
|
-
|
77
|
-
# Apply project name replacements to text files
|
78
|
-
extracted_file = target_path / member
|
79
|
-
if extracted_file.is_file() and should_process_file_for_replacements(extracted_file):
|
80
|
-
replace_project_name(extracted_file, project_name)
|
81
|
-
|
82
|
-
click.echo(f"✅ Extracted {files_extracted} files from template")
|
83
|
-
|
84
|
-
except zipfile.BadZipFile:
|
85
|
-
raise ValueError(f"Invalid template archive: {archive_path}")
|
86
|
-
except Exception as e:
|
87
|
-
raise RuntimeError(f"Failed to extract template: {e}")
|
12
|
+
import zipfile
|
88
13
|
|
14
|
+
# GitHub template URL
|
15
|
+
TEMPLATE_URL = "https://github.com/markolofsen/django-cfg/archive/refs/heads/main.zip"
|
89
16
|
|
90
|
-
def should_process_file_for_replacements(file_path: Path) -> bool:
|
91
|
-
"""Check if file should be processed for project name replacements."""
|
92
|
-
text_extensions = {'.py', '.yaml', '.yml', '.json', '.toml', '.txt', '.md', '.html', '.css', '.js', '.conf', '.sh'}
|
93
|
-
return file_path.suffix.lower() in text_extensions
|
94
17
|
|
18
|
+
def download_template(url: str) -> Path:
|
19
|
+
"""Download template archive from GitHub."""
|
20
|
+
click.echo("📥 Downloading template from GitHub...")
|
95
21
|
|
96
|
-
def replace_project_name(file_path: Path, project_name: str) -> None:
|
97
|
-
"""Replace template project name with actual project name."""
|
98
22
|
try:
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
def create_readme(target_path: Path, project_name: str) -> None:
|
124
|
-
"""Create a README.md file for the new project."""
|
125
|
-
readme_content = f"""# {project_name}
|
126
|
-
|
127
|
-
A Django project powered by **django-cfg** - the production-ready Django configuration framework.
|
128
|
-
|
129
|
-
## 🚀 Features
|
130
|
-
|
131
|
-
This project includes:
|
132
|
-
|
133
|
-
- **🔧 Type-safe Configuration** - Pydantic v2 models with validation
|
134
|
-
- **📱 Twilio Integration** - OTP services (WhatsApp, SMS, Email)
|
135
|
-
- **📧 Email Services** - SendGrid integration
|
136
|
-
- **💬 Telegram Bot** - Notifications and alerts
|
137
|
-
- **🎨 Modern Admin** - Unfold admin interface
|
138
|
-
- **📊 API Documentation** - Auto-generated OpenAPI/Swagger
|
139
|
-
- **🔐 JWT Authentication** - Ready-to-use auth system
|
140
|
-
- **🗃️ Multi-database Support** - With automatic routing
|
141
|
-
- **⚡ Background Tasks** - Dramatiq task processing
|
142
|
-
- **🌐 Ngrok Integration** - Easy webhook testing
|
143
|
-
- **🐳 Docker Ready** - Complete containerization
|
144
|
-
|
145
|
-
## 📦 Quick Start
|
146
|
-
|
147
|
-
1. **Install Dependencies**
|
148
|
-
```bash
|
149
|
-
# Using Poetry (recommended)
|
150
|
-
poetry install
|
151
|
-
|
152
|
-
# Or using pip
|
153
|
-
pip install -r requirements.txt
|
154
|
-
```
|
155
|
-
|
156
|
-
2. **Configure Environment**
|
157
|
-
```bash
|
158
|
-
# Copy and edit configuration
|
159
|
-
cp api/environment/config.dev.yaml api/environment/config.local.yaml
|
160
|
-
# Edit config.local.yaml with your settings
|
161
|
-
```
|
162
|
-
|
163
|
-
3. **Setup Database**
|
164
|
-
```bash
|
165
|
-
python manage.py migrate
|
166
|
-
python manage.py createsuperuser
|
167
|
-
```
|
168
|
-
|
169
|
-
4. **Populate Sample Data** (Optional)
|
170
|
-
```bash
|
171
|
-
python manage.py populate_sample_data
|
172
|
-
```
|
173
|
-
|
174
|
-
5. **Run Development Server**
|
175
|
-
```bash
|
176
|
-
python manage.py runserver
|
177
|
-
```
|
178
|
-
|
179
|
-
## 🔧 Configuration
|
180
|
-
|
181
|
-
Edit `api/environment/config.dev.yaml` (or create `config.local.yaml`) to configure:
|
182
|
-
|
183
|
-
- **Database connections** (PostgreSQL, MySQL, SQLite)
|
184
|
-
- **Email settings** (SMTP, SendGrid)
|
185
|
-
- **Twilio credentials** (Account SID, Auth Token, Verify Service SID)
|
186
|
-
- **Telegram bot** (Bot Token, Chat ID)
|
187
|
-
- **API keys** (OpenAI, OpenRouter, etc.)
|
188
|
-
- **Cache settings** (Redis)
|
189
|
-
|
190
|
-
## 📱 Twilio OTP Usage
|
191
|
-
|
192
|
-
```python
|
193
|
-
from django_cfg import send_sms_otp, send_whatsapp_otp, send_email_otp, verify_otp
|
194
|
-
|
195
|
-
# Send SMS OTP
|
196
|
-
success, message = send_sms_otp("+1234567890")
|
197
|
-
|
198
|
-
# Send WhatsApp OTP with SMS fallback
|
199
|
-
success, message = send_whatsapp_otp("+1234567890", fallback_to_sms=True)
|
200
|
-
|
201
|
-
# Send Email OTP
|
202
|
-
success, message, code = send_email_otp("user@example.com")
|
203
|
-
|
204
|
-
# Verify OTP
|
205
|
-
is_valid, result = verify_otp("+1234567890", "123456")
|
206
|
-
```
|
23
|
+
# Create temp file
|
24
|
+
temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.zip')
|
25
|
+
temp_path = Path(temp_file.name)
|
26
|
+
|
27
|
+
# Download with progress
|
28
|
+
with urllib.request.urlopen(url) as response:
|
29
|
+
total_size = int(response.headers.get('content-length', 0))
|
30
|
+
downloaded = 0
|
31
|
+
chunk_size = 8192
|
32
|
+
|
33
|
+
with open(temp_path, 'wb') as f:
|
34
|
+
while True:
|
35
|
+
chunk = response.read(chunk_size)
|
36
|
+
if not chunk:
|
37
|
+
break
|
38
|
+
f.write(chunk)
|
39
|
+
downloaded += len(chunk)
|
40
|
+
|
41
|
+
if total_size > 0:
|
42
|
+
progress = (downloaded / total_size) * 100
|
43
|
+
click.echo(f"\r Progress: {progress:.1f}%", nl=False)
|
44
|
+
|
45
|
+
click.echo("\n✅ Template downloaded successfully")
|
46
|
+
return temp_path
|
207
47
|
|
208
|
-
|
48
|
+
except Exception as e:
|
49
|
+
raise RuntimeError(f"Failed to download template: {e}")
|
209
50
|
|
210
|
-
```bash
|
211
|
-
# Build and run with Docker Compose
|
212
|
-
docker-compose up -d
|
213
51
|
|
214
|
-
|
215
|
-
|
216
|
-
|
52
|
+
def extract_template(archive_path: Path, target_path: Path) -> None:
|
53
|
+
"""Extract template archive to target directory."""
|
54
|
+
click.echo("📂 Extracting template...")
|
217
55
|
|
218
|
-
|
56
|
+
try:
|
57
|
+
with zipfile.ZipFile(archive_path, 'r') as archive:
|
58
|
+
members = archive.namelist()
|
219
59
|
|
220
|
-
|
221
|
-
|
222
|
-
- **Django CFG Docs**: [djangocfg.com](https://djangocfg.com)
|
60
|
+
# Find the root folder name (django-cfg-main)
|
61
|
+
root_folder = members[0].split('/')[0] if members else None
|
223
62
|
|
224
|
-
|
63
|
+
if not root_folder:
|
64
|
+
raise ValueError("Archive structure is invalid")
|
225
65
|
|
226
|
-
|
227
|
-
|
228
|
-
python manage.py runserver_ngrok
|
229
|
-
|
230
|
-
# Generate OpenAPI clients
|
231
|
-
python manage.py generate_openapi_clients
|
232
|
-
|
233
|
-
# Translate content (if using i18n)
|
234
|
-
python manage.py translate_content
|
235
|
-
```
|
236
|
-
|
237
|
-
## 📁 Project Structure
|
66
|
+
# Path to django project in archive: django-cfg-main/libs/django_cfg_example/django/
|
67
|
+
template_prefix = f"{root_folder}/libs/django_cfg_example/django/"
|
238
68
|
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
│ └── urls.py # Root URL configuration
|
246
|
-
├── apps/ # Django applications
|
247
|
-
│ ├── blog/ # Blog app example
|
248
|
-
│ ├── profiles/ # User profiles
|
249
|
-
│ └── shop/ # E-commerce example
|
250
|
-
├── core/ # Core utilities and management commands
|
251
|
-
├── docker/ # Docker configuration
|
252
|
-
├── static/ # Static files
|
253
|
-
├── templates/ # Django templates
|
254
|
-
└── manage.py # Django management script
|
255
|
-
```
|
69
|
+
# Extract only files from the django/ folder
|
70
|
+
extracted_files = 0
|
71
|
+
for member in members:
|
72
|
+
# Skip if not in template path
|
73
|
+
if not member.startswith(template_prefix):
|
74
|
+
continue
|
256
75
|
|
257
|
-
|
76
|
+
# Skip the django_cfg folder (local package)
|
77
|
+
if f"{root_folder}/libs/django_cfg_example/django_cfg/" in member:
|
78
|
+
continue
|
258
79
|
|
259
|
-
|
260
|
-
|
80
|
+
# Calculate relative path (remove template_prefix)
|
81
|
+
relative_path = member[len(template_prefix):]
|
261
82
|
|
262
|
-
|
83
|
+
# Skip empty paths (directory markers)
|
84
|
+
if not relative_path:
|
85
|
+
continue
|
263
86
|
|
264
|
-
|
87
|
+
# Target file path
|
88
|
+
target_file = target_path / relative_path
|
265
89
|
|
266
|
-
|
90
|
+
# Extract file
|
91
|
+
if member.endswith('/'):
|
92
|
+
# Create directory
|
93
|
+
target_file.mkdir(parents=True, exist_ok=True)
|
94
|
+
else:
|
95
|
+
# Create parent directories
|
96
|
+
target_file.parent.mkdir(parents=True, exist_ok=True)
|
267
97
|
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
with open(readme_path, 'w', encoding='utf-8') as f:
|
273
|
-
f.write(readme_content)
|
98
|
+
# Extract file content
|
99
|
+
with archive.open(member) as source:
|
100
|
+
with open(target_file, 'wb') as target:
|
101
|
+
target.write(source.read())
|
274
102
|
|
103
|
+
extracted_files += 1
|
275
104
|
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
Args:
|
281
|
-
target_path: Project directory
|
282
|
-
command: Command to run (without poetry/python prefix)
|
283
|
-
description: Description for user feedback
|
284
|
-
use_poetry: Use Poetry if True, pip/python if False
|
285
|
-
check: Raise exception on error if True
|
286
|
-
|
287
|
-
Returns:
|
288
|
-
(success: bool, output: str)
|
289
|
-
"""
|
290
|
-
try:
|
291
|
-
if use_poetry:
|
292
|
-
cmd = ["poetry", "run"] + command
|
293
|
-
else:
|
294
|
-
# For pip/python commands, use system python
|
295
|
-
if command[0] == "python":
|
296
|
-
cmd = [sys.executable] + command[1:]
|
297
|
-
else:
|
298
|
-
cmd = command
|
299
|
-
|
300
|
-
result = subprocess.run(
|
301
|
-
cmd,
|
302
|
-
cwd=target_path,
|
303
|
-
check=check,
|
304
|
-
capture_output=True,
|
305
|
-
text=True
|
306
|
-
)
|
307
|
-
|
308
|
-
return True, result.stdout
|
309
|
-
|
310
|
-
except subprocess.CalledProcessError as e:
|
311
|
-
return False, f"Error: {e}\nstdout: {e.stdout}\nstderr: {e.stderr}"
|
312
|
-
except FileNotFoundError as e:
|
313
|
-
return False, f"Command not found: {e}"
|
314
|
-
|
315
|
-
|
316
|
-
def install_dependencies(target_path: Path, use_poetry: bool = True) -> bool:
|
317
|
-
"""Install project dependencies using Poetry or pip."""
|
318
|
-
click.echo("📦 Installing dependencies...")
|
319
|
-
|
320
|
-
if use_poetry:
|
321
|
-
success, output = run_command(target_path, ["poetry", "install"], "Installing with Poetry", use_poetry=False)
|
322
|
-
else:
|
323
|
-
success, output = run_command(target_path, ["python", "-m", "pip", "install", "-r", "requirements.txt"], "Installing with pip", use_poetry=False)
|
324
|
-
|
325
|
-
if success:
|
326
|
-
click.echo("✅ Dependencies installed successfully")
|
327
|
-
return True
|
328
|
-
else:
|
329
|
-
click.echo(f"⚠️ Warning: Failed to install dependencies: {output}", err=True)
|
330
|
-
return False
|
331
|
-
|
332
|
-
|
333
|
-
def setup_project_structure(target_path: Path) -> bool:
|
334
|
-
"""Create necessary directories for the project."""
|
335
|
-
try:
|
336
|
-
# Create db directory for SQLite database
|
337
|
-
db_dir = target_path / "db"
|
338
|
-
db_dir.mkdir(exist_ok=True)
|
339
|
-
click.echo(f"📁 Created database directory: {db_dir}")
|
340
|
-
|
341
|
-
# Create cache directory
|
342
|
-
cache_dir = target_path / "cache"
|
343
|
-
cache_dir.mkdir(exist_ok=True)
|
344
|
-
click.echo(f"📁 Created cache directory: {cache_dir}")
|
345
|
-
|
346
|
-
return True
|
105
|
+
click.echo(f"✅ Template extracted successfully ({extracted_files} files)")
|
106
|
+
|
107
|
+
except zipfile.BadZipFile:
|
108
|
+
raise ValueError(f"Invalid template archive")
|
347
109
|
except Exception as e:
|
348
|
-
|
349
|
-
return False
|
350
|
-
|
351
|
-
|
352
|
-
def run_initial_migrations(target_path: Path, use_poetry: bool = True) -> bool:
|
353
|
-
"""Run initial Django migrations."""
|
354
|
-
click.echo("🔄 Running initial migrations...")
|
355
|
-
|
356
|
-
# Try cli migrator first, fallback to manage.py migrate
|
357
|
-
success, output = run_command(target_path, ["cli", "migrator"], "Running migrations", use_poetry, check=False)
|
358
|
-
|
359
|
-
if not success:
|
360
|
-
click.echo(" Falling back to manage.py migrate...")
|
361
|
-
success, output = run_command(target_path, ["python", "manage.py", "migrate"], "Running migrations", use_poetry)
|
362
|
-
|
363
|
-
if success:
|
364
|
-
click.echo("✅ Initial migrations completed successfully")
|
365
|
-
return True
|
366
|
-
else:
|
367
|
-
click.echo(f"⚠️ Warning: Failed to run migrations: {output}", err=True)
|
368
|
-
return False
|
369
|
-
|
370
|
-
|
371
|
-
def populate_sample_data(target_path: Path, use_poetry: bool = True) -> bool:
|
372
|
-
"""Populate database with sample data."""
|
373
|
-
click.echo("👥 Populating sample data (users, blog posts, products)...")
|
374
|
-
|
375
|
-
success, output = run_command(
|
376
|
-
target_path,
|
377
|
-
["python", "manage.py", "populate_sample_data", "--users", "10", "--posts", "20", "--products", "30"],
|
378
|
-
"Populating sample data",
|
379
|
-
use_poetry
|
380
|
-
)
|
381
|
-
|
382
|
-
if success:
|
383
|
-
click.echo("✅ Sample data populated successfully")
|
384
|
-
click.echo(" 📝 Created 10 test users, 20 blog posts, 30 products")
|
385
|
-
return True
|
386
|
-
else:
|
387
|
-
click.echo(f"⚠️ Warning: Failed to populate sample data: {output}", err=True)
|
388
|
-
return False
|
110
|
+
raise RuntimeError(f"Failed to extract template: {e}")
|
389
111
|
|
390
112
|
|
391
113
|
@click.command()
|
392
|
-
@click.argument("project_name")
|
393
114
|
@click.option(
|
394
115
|
"--path",
|
395
116
|
"-p",
|
@@ -397,177 +118,73 @@ def populate_sample_data(target_path: Path, use_poetry: bool = True) -> bool:
|
|
397
118
|
default=".",
|
398
119
|
help="Directory where to create the project (default: current directory)"
|
399
120
|
)
|
400
|
-
@click.option(
|
401
|
-
"--no-deps",
|
402
|
-
is_flag=True,
|
403
|
-
help="Skip automatic dependency installation"
|
404
|
-
)
|
405
|
-
@click.option(
|
406
|
-
"--use-pip",
|
407
|
-
is_flag=True,
|
408
|
-
help="Use pip instead of Poetry for dependency installation"
|
409
|
-
)
|
410
121
|
@click.option(
|
411
122
|
"--force",
|
123
|
+
"-f",
|
412
124
|
is_flag=True,
|
413
|
-
help="Overwrite existing
|
414
|
-
)
|
415
|
-
@click.option(
|
416
|
-
"--no-setup",
|
417
|
-
is_flag=True,
|
418
|
-
help="Skip automatic project setup (directories, migrations)"
|
125
|
+
help="Overwrite existing files if they exist"
|
419
126
|
)
|
420
|
-
|
421
|
-
"--no-sample-data",
|
422
|
-
is_flag=True,
|
423
|
-
help="Skip sample data population (users, posts, products)"
|
424
|
-
)
|
425
|
-
def create_project(project_name: str, path: str, no_deps: bool, use_pip: bool, force: bool, no_setup: bool, no_sample_data: bool):
|
127
|
+
def create_project(path: str, force: bool):
|
426
128
|
"""
|
427
129
|
🚀 Create a new Django project with django-cfg
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
PROJECT_NAME: Name of the new Django project
|
433
|
-
|
130
|
+
|
131
|
+
Downloads the latest django-cfg template from GitHub and extracts it.
|
132
|
+
|
434
133
|
Examples:
|
435
|
-
|
436
|
-
#
|
437
|
-
django-cfg create-project
|
438
|
-
|
439
|
-
#
|
440
|
-
django-cfg create-project
|
441
|
-
|
442
|
-
#
|
443
|
-
django-cfg create-project
|
444
|
-
|
445
|
-
# Use pip instead of Poetry
|
446
|
-
django-cfg create-project "My Project" --use-pip
|
447
|
-
|
448
|
-
# Skip automatic setup (directories, migrations)
|
449
|
-
django-cfg create-project "My Project" --no-setup
|
450
|
-
|
451
|
-
# Skip sample data creation (users, posts, products)
|
452
|
-
django-cfg create-project "My Project" --no-sample-data
|
134
|
+
|
135
|
+
# Extract to current directory
|
136
|
+
django-cfg create-project
|
137
|
+
|
138
|
+
# Extract to specific directory
|
139
|
+
django-cfg create-project --path ./my-project/
|
140
|
+
|
141
|
+
# Overwrite existing files
|
142
|
+
django-cfg create-project --force
|
453
143
|
"""
|
454
|
-
|
455
|
-
# Validate project name
|
456
|
-
if not validate_project_name(project_name):
|
457
|
-
click.echo("❌ Invalid project name", err=True)
|
458
|
-
return
|
459
|
-
|
144
|
+
|
460
145
|
# Determine target path
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
# Check if target directory exists
|
466
|
-
if target_path.exists():
|
146
|
+
target_path = Path(path).resolve()
|
147
|
+
|
148
|
+
# Check if target directory exists and has files
|
149
|
+
if target_path.exists() and any(target_path.iterdir()):
|
467
150
|
if not force:
|
468
|
-
click.echo(f"❌ Directory '{target_path}'
|
151
|
+
click.echo(f"❌ Directory '{target_path}' is not empty. Use --force to overwrite.", err=True)
|
469
152
|
return
|
470
153
|
else:
|
471
|
-
click.echo(f"⚠️
|
472
|
-
|
473
|
-
|
154
|
+
click.echo(f"⚠️ Directory is not empty, files will be overwritten...")
|
155
|
+
|
156
|
+
temp_archive = None
|
157
|
+
|
474
158
|
try:
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
click.echo(f"📋 Using template archive: {archive_path.name}")
|
483
|
-
|
159
|
+
click.echo(f"🚀 Creating Django project from GitHub")
|
160
|
+
click.echo(f"📁 Target location: {target_path}")
|
161
|
+
click.echo()
|
162
|
+
|
163
|
+
# Download template from GitHub
|
164
|
+
temp_archive = download_template(TEMPLATE_URL)
|
165
|
+
|
484
166
|
# Create target directory
|
485
167
|
target_path.mkdir(parents=True, exist_ok=True)
|
486
|
-
|
487
|
-
# Extract template
|
488
|
-
extract_template(
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
click.echo(f"✅ Project '{project_name}' created successfully!")
|
168
|
+
|
169
|
+
# Extract template
|
170
|
+
extract_template(temp_archive, target_path)
|
171
|
+
|
172
|
+
click.echo()
|
173
|
+
click.echo(f"✅ Project created successfully!")
|
494
174
|
click.echo(f"📁 Location: {target_path}")
|
495
|
-
|
496
|
-
# Setup project structure
|
497
|
-
if not no_setup:
|
498
|
-
click.echo("\n🔧 Setting up project structure...")
|
499
|
-
setup_project_structure(target_path)
|
500
|
-
|
501
|
-
# Install dependencies if requested
|
502
|
-
deps_installed = False
|
503
|
-
if not no_deps:
|
504
|
-
install_success = install_dependencies(target_path, not use_pip)
|
505
|
-
if install_success:
|
506
|
-
deps_installed = True
|
507
|
-
else:
|
508
|
-
click.echo("💡 You can install dependencies manually later:")
|
509
|
-
if not use_pip:
|
510
|
-
click.echo(" poetry install")
|
511
|
-
else:
|
512
|
-
click.echo(" pip install -r requirements.txt")
|
513
|
-
|
514
|
-
# Run initial setup if dependencies were installed
|
515
|
-
if deps_installed and not no_setup:
|
516
|
-
click.echo("\n🔄 Running initial project setup...")
|
517
|
-
migration_success = run_initial_migrations(target_path, not use_pip)
|
518
|
-
|
519
|
-
if migration_success:
|
520
|
-
# Populate sample data if requested
|
521
|
-
if not no_sample_data:
|
522
|
-
sample_data_success = populate_sample_data(target_path, not use_pip)
|
523
|
-
if sample_data_success:
|
524
|
-
click.echo("✅ Project is ready to use with sample data!")
|
525
|
-
click.echo("💡 Login credentials: username/password for any test user")
|
526
|
-
else:
|
527
|
-
click.echo("✅ Project is ready to use!")
|
528
|
-
click.echo("💡 You can populate sample data later:")
|
529
|
-
if not use_pip:
|
530
|
-
click.echo(" poetry run python manage.py populate_sample_data")
|
531
|
-
else:
|
532
|
-
click.echo(" python manage.py populate_sample_data")
|
533
|
-
else:
|
534
|
-
click.echo("✅ Project is ready to use!")
|
535
|
-
else:
|
536
|
-
click.echo("💡 You can run migrations manually later:")
|
537
|
-
if not use_pip:
|
538
|
-
click.echo(" poetry run cli migrator")
|
539
|
-
else:
|
540
|
-
click.echo(" python manage.py migrate")
|
541
|
-
|
175
|
+
|
542
176
|
# Show next steps
|
543
|
-
click.echo(
|
544
|
-
click.echo("
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
click.echo(" # Edit api/environment/config.dev.yaml with your settings")
|
555
|
-
if not deps_installed:
|
556
|
-
if not use_pip:
|
557
|
-
click.echo(" poetry run cli migrator")
|
558
|
-
else:
|
559
|
-
click.echo(" python manage.py migrate")
|
560
|
-
click.echo(" python manage.py createsuperuser")
|
561
|
-
else:
|
562
|
-
click.echo(" # Edit api/environment/config.dev.yaml with your settings")
|
563
|
-
click.echo(" python manage.py createsuperuser")
|
564
|
-
|
565
|
-
if not use_pip:
|
566
|
-
click.echo(" poetry run cli runserver")
|
567
|
-
else:
|
568
|
-
click.echo(" python manage.py runserver")
|
569
|
-
|
570
|
-
click.echo("\n💡 Features included:")
|
177
|
+
click.echo()
|
178
|
+
click.echo("📋 Next steps:")
|
179
|
+
if target_path != Path.cwd():
|
180
|
+
click.echo(f" cd {target_path}")
|
181
|
+
click.echo(" poetry install # or: pip install -r requirements.txt")
|
182
|
+
click.echo(" python manage.py migrate")
|
183
|
+
click.echo(" python manage.py createsuperuser")
|
184
|
+
click.echo(" python manage.py runserver")
|
185
|
+
|
186
|
+
click.echo()
|
187
|
+
click.echo("💡 Features included:")
|
571
188
|
click.echo(" 🔧 Type-safe configuration with Pydantic v2")
|
572
189
|
click.echo(" 📱 Twilio integration (WhatsApp, SMS, Email OTP)")
|
573
190
|
click.echo(" 📧 Email services with SendGrid")
|
@@ -578,25 +195,19 @@ def create_project(project_name: str, path: str, no_deps: bool, use_pip: bool, f
|
|
578
195
|
click.echo(" 🗃️ Multi-database support with routing")
|
579
196
|
click.echo(" ⚡ Background task processing")
|
580
197
|
click.echo(" 🐳 Docker deployment ready")
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
except FileNotFoundError as e:
|
588
|
-
click.echo(f"❌ Template archive not found: {e}", err=True)
|
589
|
-
click.echo("💡 Make sure django-cfg is properly installed")
|
590
|
-
click.echo("💡 In development, run: python scripts/template_manager.py create")
|
591
|
-
|
592
|
-
except (ValueError, RuntimeError) as e:
|
593
|
-
click.echo(f"❌ Template error: {e}", err=True)
|
594
|
-
# Clean up on error
|
595
|
-
if target_path.exists():
|
596
|
-
shutil.rmtree(target_path, ignore_errors=True)
|
597
|
-
|
198
|
+
|
199
|
+
click.echo()
|
200
|
+
click.echo("📚 Documentation: https://github.com/markolofsen/django-cfg")
|
201
|
+
click.echo("🌐 Developed by Unrealon.com — Complex parsers on demand")
|
202
|
+
|
598
203
|
except Exception as e:
|
599
204
|
click.echo(f"❌ Error creating project: {e}", err=True)
|
600
205
|
# Clean up on error
|
601
206
|
if target_path.exists():
|
602
207
|
shutil.rmtree(target_path, ignore_errors=True)
|
208
|
+
raise
|
209
|
+
|
210
|
+
finally:
|
211
|
+
# Clean up temp file
|
212
|
+
if temp_archive and temp_archive.exists():
|
213
|
+
temp_archive.unlink()
|