django-cfg 1.3.7__py3-none-any.whl → 1.3.9__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/__init__.py +24 -8
- django_cfg/apps/accounts/admin/activity_admin.py +146 -0
- django_cfg/apps/accounts/admin/filters.py +98 -22
- django_cfg/apps/accounts/admin/group_admin.py +86 -0
- django_cfg/apps/accounts/admin/inlines.py +42 -13
- django_cfg/apps/accounts/admin/otp_admin.py +115 -0
- django_cfg/apps/accounts/admin/registration_admin.py +173 -0
- django_cfg/apps/accounts/admin/resources.py +123 -19
- django_cfg/apps/accounts/admin/twilio_admin.py +327 -0
- django_cfg/apps/accounts/admin/user_admin.py +362 -0
- django_cfg/apps/agents/admin/__init__.py +17 -4
- django_cfg/apps/agents/admin/execution_admin.py +204 -183
- django_cfg/apps/agents/admin/registry_admin.py +230 -255
- django_cfg/apps/agents/admin/toolsets_admin.py +274 -321
- django_cfg/apps/agents/core/__init__.py +1 -1
- django_cfg/apps/agents/core/django_agent.py +221 -0
- django_cfg/apps/agents/core/exceptions.py +14 -0
- django_cfg/apps/agents/core/orchestrator.py +18 -3
- django_cfg/apps/knowbase/admin/__init__.py +1 -1
- django_cfg/apps/knowbase/admin/archive_admin.py +352 -640
- django_cfg/apps/knowbase/admin/chat_admin.py +258 -192
- django_cfg/apps/knowbase/admin/document_admin.py +269 -262
- django_cfg/apps/knowbase/admin/external_data_admin.py +271 -489
- django_cfg/apps/knowbase/config/settings.py +21 -4
- django_cfg/apps/knowbase/views/chat_views.py +3 -0
- django_cfg/apps/leads/admin/__init__.py +3 -1
- django_cfg/apps/leads/admin/leads_admin.py +235 -35
- django_cfg/apps/maintenance/admin/__init__.py +2 -2
- django_cfg/apps/maintenance/admin/api_key_admin.py +125 -63
- django_cfg/apps/maintenance/admin/log_admin.py +143 -61
- django_cfg/apps/maintenance/admin/scheduled_admin.py +212 -301
- django_cfg/apps/maintenance/admin/site_admin.py +213 -352
- django_cfg/apps/newsletter/admin/__init__.py +29 -2
- django_cfg/apps/newsletter/admin/newsletter_admin.py +531 -193
- django_cfg/apps/payments/admin/__init__.py +18 -27
- django_cfg/apps/payments/admin/api_keys_admin.py +179 -546
- django_cfg/apps/payments/admin/balance_admin.py +166 -632
- django_cfg/apps/payments/admin/currencies_admin.py +235 -607
- django_cfg/apps/payments/admin/endpoint_groups_admin.py +127 -0
- django_cfg/apps/payments/admin/filters.py +83 -3
- django_cfg/apps/payments/admin/networks_admin.py +258 -0
- django_cfg/apps/payments/admin/payments_admin.py +171 -461
- django_cfg/apps/payments/admin/subscriptions_admin.py +119 -636
- django_cfg/apps/payments/admin/tariffs_admin.py +248 -0
- django_cfg/apps/payments/admin_interface/serializers/payment_serializers.py +105 -34
- django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +12 -16
- django_cfg/apps/payments/admin_interface/views/__init__.py +2 -0
- django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +13 -18
- django_cfg/apps/payments/management/commands/manage_currencies.py +236 -274
- django_cfg/apps/payments/management/commands/manage_providers.py +4 -1
- django_cfg/apps/payments/middleware/api_access.py +32 -6
- django_cfg/apps/payments/migrations/0002_currency_usd_rate_currency_usd_rate_updated_at.py +26 -0
- django_cfg/apps/payments/migrations/0003_remove_provider_currency_fields.py +28 -0
- django_cfg/apps/payments/migrations/0004_add_reserved_usd_field.py +30 -0
- django_cfg/apps/payments/models/balance.py +12 -0
- django_cfg/apps/payments/models/currencies.py +106 -32
- django_cfg/apps/payments/models/managers/currency_managers.py +65 -0
- django_cfg/apps/payments/services/core/currency_service.py +35 -28
- django_cfg/apps/payments/services/core/payment_service.py +1 -1
- django_cfg/apps/payments/services/providers/__init__.py +3 -0
- django_cfg/apps/payments/services/providers/base.py +95 -39
- django_cfg/apps/payments/services/providers/models/__init__.py +40 -0
- django_cfg/apps/payments/services/providers/models/base.py +122 -0
- django_cfg/apps/payments/services/providers/models/providers.py +87 -0
- django_cfg/apps/payments/services/providers/models/universal.py +48 -0
- django_cfg/apps/payments/services/providers/nowpayments/__init__.py +31 -0
- django_cfg/apps/payments/services/providers/nowpayments/config.py +70 -0
- django_cfg/apps/payments/services/providers/nowpayments/models.py +150 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers.py +879 -0
- django_cfg/apps/payments/services/providers/{nowpayments.py → nowpayments/provider.py} +240 -209
- django_cfg/apps/payments/services/providers/nowpayments/sync.py +196 -0
- django_cfg/apps/payments/services/providers/registry.py +4 -32
- django_cfg/apps/payments/services/providers/sync_service.py +277 -0
- django_cfg/apps/payments/static/payments/js/api-client.js +23 -5
- django_cfg/apps/payments/static/payments/js/payment-form.js +65 -8
- django_cfg/apps/payments/tasks/__init__.py +39 -0
- django_cfg/apps/payments/tasks/types.py +73 -0
- django_cfg/apps/payments/tasks/usage_tracking.py +308 -0
- django_cfg/apps/payments/templates/admin/payments/_components/dashboard_header.html +23 -0
- django_cfg/apps/payments/templates/admin/payments/_components/stats_card.html +25 -0
- django_cfg/apps/payments/templates/admin/payments/_components/stats_grid.html +16 -0
- django_cfg/apps/payments/templates/admin/payments/apikey/change_list.html +39 -0
- django_cfg/apps/payments/templates/admin/payments/balance/change_list.html +50 -0
- django_cfg/apps/payments/templates/admin/payments/currency/change_list.html +40 -0
- django_cfg/apps/payments/templates/admin/payments/payment/change_list.html +48 -0
- django_cfg/apps/payments/templates/admin/payments/subscription/change_list.html +48 -0
- django_cfg/apps/payments/urls_admin.py +1 -1
- django_cfg/apps/payments/views/api/currencies.py +5 -5
- django_cfg/apps/payments/views/overview/services.py +2 -2
- django_cfg/apps/payments/views/serializers/currencies.py +4 -3
- django_cfg/apps/support/admin/__init__.py +10 -1
- django_cfg/apps/support/admin/support_admin.py +338 -141
- django_cfg/apps/tasks/admin/__init__.py +11 -0
- django_cfg/apps/tasks/admin/tasks_admin.py +430 -0
- django_cfg/config.py +1 -1
- django_cfg/core/config.py +10 -5
- django_cfg/core/generation.py +1 -1
- django_cfg/management/commands/__init__.py +13 -1
- django_cfg/management/commands/app_agent_diagnose.py +470 -0
- django_cfg/management/commands/app_agent_generate.py +342 -0
- django_cfg/management/commands/app_agent_info.py +308 -0
- django_cfg/management/commands/migrate_all.py +9 -3
- django_cfg/management/commands/migrator.py +11 -6
- django_cfg/management/commands/rundramatiq.py +3 -2
- django_cfg/middleware/__init__.py +0 -2
- django_cfg/models/api_keys.py +115 -0
- django_cfg/modules/django_admin/__init__.py +64 -0
- django_cfg/modules/django_admin/decorators/__init__.py +13 -0
- django_cfg/modules/django_admin/decorators/actions.py +106 -0
- django_cfg/modules/django_admin/decorators/display.py +106 -0
- django_cfg/modules/django_admin/mixins/__init__.py +14 -0
- django_cfg/modules/django_admin/mixins/display_mixin.py +81 -0
- django_cfg/modules/django_admin/mixins/optimization_mixin.py +41 -0
- django_cfg/modules/django_admin/mixins/standalone_actions_mixin.py +202 -0
- django_cfg/modules/django_admin/models/__init__.py +20 -0
- django_cfg/modules/django_admin/models/action_models.py +33 -0
- django_cfg/modules/django_admin/models/badge_models.py +20 -0
- django_cfg/modules/django_admin/models/base.py +26 -0
- django_cfg/modules/django_admin/models/display_models.py +31 -0
- django_cfg/modules/django_admin/utils/badges.py +159 -0
- django_cfg/modules/django_admin/utils/displays.py +247 -0
- django_cfg/modules/django_app_agent/__init__.py +87 -0
- django_cfg/modules/django_app_agent/agents/__init__.py +40 -0
- django_cfg/modules/django_app_agent/agents/base/__init__.py +24 -0
- django_cfg/modules/django_app_agent/agents/base/agent.py +354 -0
- django_cfg/modules/django_app_agent/agents/base/context.py +236 -0
- django_cfg/modules/django_app_agent/agents/base/executor.py +430 -0
- django_cfg/modules/django_app_agent/agents/generation/__init__.py +12 -0
- django_cfg/modules/django_app_agent/agents/generation/app_generator/__init__.py +15 -0
- django_cfg/modules/django_app_agent/agents/generation/app_generator/config_validator.py +147 -0
- django_cfg/modules/django_app_agent/agents/generation/app_generator/main.py +99 -0
- django_cfg/modules/django_app_agent/agents/generation/app_generator/models.py +32 -0
- django_cfg/modules/django_app_agent/agents/generation/app_generator/prompt_manager.py +290 -0
- django_cfg/modules/django_app_agent/agents/interfaces.py +376 -0
- django_cfg/modules/django_app_agent/core/__init__.py +33 -0
- django_cfg/modules/django_app_agent/core/config.py +300 -0
- django_cfg/modules/django_app_agent/core/exceptions.py +359 -0
- django_cfg/modules/django_app_agent/models/__init__.py +71 -0
- django_cfg/modules/django_app_agent/models/base.py +283 -0
- django_cfg/modules/django_app_agent/models/context.py +496 -0
- django_cfg/modules/django_app_agent/models/enums.py +481 -0
- django_cfg/modules/django_app_agent/models/requests.py +500 -0
- django_cfg/modules/django_app_agent/models/responses.py +585 -0
- django_cfg/modules/django_app_agent/pytest.ini +6 -0
- django_cfg/modules/django_app_agent/services/__init__.py +42 -0
- django_cfg/modules/django_app_agent/services/app_generator/__init__.py +30 -0
- django_cfg/modules/django_app_agent/services/app_generator/ai_integration.py +133 -0
- django_cfg/modules/django_app_agent/services/app_generator/context.py +40 -0
- django_cfg/modules/django_app_agent/services/app_generator/main.py +202 -0
- django_cfg/modules/django_app_agent/services/app_generator/structure.py +316 -0
- django_cfg/modules/django_app_agent/services/app_generator/validation.py +125 -0
- django_cfg/modules/django_app_agent/services/base.py +437 -0
- django_cfg/modules/django_app_agent/services/context_builder/__init__.py +34 -0
- django_cfg/modules/django_app_agent/services/context_builder/code_extractor.py +141 -0
- django_cfg/modules/django_app_agent/services/context_builder/context_generator.py +276 -0
- django_cfg/modules/django_app_agent/services/context_builder/main.py +272 -0
- django_cfg/modules/django_app_agent/services/context_builder/models.py +40 -0
- django_cfg/modules/django_app_agent/services/context_builder/pattern_analyzer.py +85 -0
- django_cfg/modules/django_app_agent/services/project_scanner/__init__.py +31 -0
- django_cfg/modules/django_app_agent/services/project_scanner/app_discovery.py +311 -0
- django_cfg/modules/django_app_agent/services/project_scanner/main.py +221 -0
- django_cfg/modules/django_app_agent/services/project_scanner/models.py +59 -0
- django_cfg/modules/django_app_agent/services/project_scanner/pattern_detection.py +94 -0
- django_cfg/modules/django_app_agent/services/questioning_service/__init__.py +28 -0
- django_cfg/modules/django_app_agent/services/questioning_service/main.py +273 -0
- django_cfg/modules/django_app_agent/services/questioning_service/models.py +111 -0
- django_cfg/modules/django_app_agent/services/questioning_service/question_generator.py +251 -0
- django_cfg/modules/django_app_agent/services/questioning_service/response_processor.py +347 -0
- django_cfg/modules/django_app_agent/services/questioning_service/session_manager.py +356 -0
- django_cfg/modules/django_app_agent/services/report_service.py +332 -0
- django_cfg/modules/django_app_agent/services/template_manager/__init__.py +18 -0
- django_cfg/modules/django_app_agent/services/template_manager/jinja_engine.py +236 -0
- django_cfg/modules/django_app_agent/services/template_manager/main.py +159 -0
- django_cfg/modules/django_app_agent/services/template_manager/models.py +36 -0
- django_cfg/modules/django_app_agent/services/template_manager/template_loader.py +100 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/admin.py.j2 +105 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/apps.py.j2 +31 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_config.py.j2 +44 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_module.py.j2 +81 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/forms.py.j2 +107 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/models.py.j2 +139 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/serializers.py.j2 +91 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/tests.py.j2 +195 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/urls.py.j2 +35 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/views.py.j2 +211 -0
- django_cfg/modules/django_app_agent/services/template_manager/variable_processor.py +200 -0
- django_cfg/modules/django_app_agent/services/validation_service/__init__.py +25 -0
- django_cfg/modules/django_app_agent/services/validation_service/django_validator.py +333 -0
- django_cfg/modules/django_app_agent/services/validation_service/main.py +242 -0
- django_cfg/modules/django_app_agent/services/validation_service/models.py +66 -0
- django_cfg/modules/django_app_agent/services/validation_service/quality_validator.py +352 -0
- django_cfg/modules/django_app_agent/services/validation_service/security_validator.py +272 -0
- django_cfg/modules/django_app_agent/services/validation_service/syntax_validator.py +203 -0
- django_cfg/modules/django_app_agent/ui/__init__.py +25 -0
- django_cfg/modules/django_app_agent/ui/cli.py +419 -0
- django_cfg/modules/django_app_agent/ui/rich_components.py +622 -0
- django_cfg/modules/django_app_agent/utils/__init__.py +38 -0
- django_cfg/modules/django_app_agent/utils/logging.py +360 -0
- django_cfg/modules/django_app_agent/utils/validation.py +417 -0
- django_cfg/modules/django_currency/__init__.py +2 -2
- django_cfg/modules/django_currency/clients/__init__.py +2 -2
- django_cfg/modules/django_currency/clients/hybrid_client.py +587 -0
- django_cfg/modules/django_currency/core/converter.py +12 -12
- django_cfg/modules/django_currency/database/__init__.py +2 -2
- django_cfg/modules/django_currency/database/database_loader.py +93 -42
- django_cfg/modules/django_llm/llm/client.py +10 -2
- django_cfg/modules/django_unfold/callbacks/actions.py +1 -1
- django_cfg/modules/django_unfold/callbacks/statistics.py +1 -1
- django_cfg/modules/django_unfold/dashboard.py +14 -13
- django_cfg/modules/django_unfold/models/config.py +1 -1
- django_cfg/registry/core.py +3 -0
- django_cfg/registry/third_party.py +2 -2
- django_cfg/template_archive/django_sample.zip +0 -0
- {django_cfg-1.3.7.dist-info → django_cfg-1.3.9.dist-info}/METADATA +2 -1
- {django_cfg-1.3.7.dist-info → django_cfg-1.3.9.dist-info}/RECORD +223 -117
- django_cfg/apps/accounts/admin/activity.py +0 -96
- django_cfg/apps/accounts/admin/group.py +0 -17
- django_cfg/apps/accounts/admin/otp.py +0 -59
- django_cfg/apps/accounts/admin/registration_source.py +0 -97
- django_cfg/apps/accounts/admin/twilio_response.py +0 -227
- django_cfg/apps/accounts/admin/user.py +0 -300
- django_cfg/apps/agents/core/agent.py +0 -281
- django_cfg/apps/payments/admin_interface/old/payments/base.html +0 -175
- django_cfg/apps/payments/admin_interface/old/payments/components/dev_tool_card.html +0 -125
- django_cfg/apps/payments/admin_interface/old/payments/components/loading_spinner.html +0 -16
- django_cfg/apps/payments/admin_interface/old/payments/components/ngrok_status_card.html +0 -113
- django_cfg/apps/payments/admin_interface/old/payments/components/notification.html +0 -27
- django_cfg/apps/payments/admin_interface/old/payments/components/provider_card.html +0 -86
- django_cfg/apps/payments/admin_interface/old/payments/components/status_card.html +0 -35
- django_cfg/apps/payments/admin_interface/old/payments/currency_converter.html +0 -382
- django_cfg/apps/payments/admin_interface/old/payments/payment_dashboard.html +0 -309
- django_cfg/apps/payments/admin_interface/old/payments/payment_form.html +0 -303
- django_cfg/apps/payments/admin_interface/old/payments/payment_list.html +0 -382
- django_cfg/apps/payments/admin_interface/old/payments/payment_status.html +0 -500
- django_cfg/apps/payments/admin_interface/old/payments/webhook_dashboard.html +0 -518
- django_cfg/apps/payments/admin_interface/old/static/payments/css/components.css +0 -619
- django_cfg/apps/payments/admin_interface/old/static/payments/css/dashboard.css +0 -188
- django_cfg/apps/payments/admin_interface/old/static/payments/js/components.js +0 -545
- django_cfg/apps/payments/admin_interface/old/static/payments/js/ngrok-status.js +0 -163
- django_cfg/apps/payments/admin_interface/old/static/payments/js/utils.js +0 -412
- django_cfg/apps/tasks/admin.py +0 -320
- django_cfg/middleware/static_nocache.py +0 -55
- django_cfg/modules/django_currency/clients/yahoo_client.py +0 -157
- /django_cfg/modules/{django_unfold → django_admin}/icons/README.md +0 -0
- /django_cfg/modules/{django_unfold → django_admin}/icons/__init__.py +0 -0
- /django_cfg/modules/{django_unfold → django_admin}/icons/constants.py +0 -0
- /django_cfg/modules/{django_unfold → django_admin}/icons/generate_icons.py +0 -0
- {django_cfg-1.3.7.dist-info → django_cfg-1.3.9.dist-info}/WHEEL +0 -0
- {django_cfg-1.3.7.dist-info → django_cfg-1.3.9.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.3.7.dist-info → django_cfg-1.3.9.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,44 @@
|
|
1
|
+
"""
|
2
|
+
Django-CFG configuration for {{ app_name }} application.
|
3
|
+
|
4
|
+
{{ description }}
|
5
|
+
"""
|
6
|
+
|
7
|
+
from django_cfg.config import BaseCfgConfig
|
8
|
+
from pydantic import Field
|
9
|
+
from typing import Optional, List
|
10
|
+
|
11
|
+
|
12
|
+
class {{ app_name|pascal_case }}Config(BaseCfgConfig):
|
13
|
+
"""Configuration for {{ app_name }} application."""
|
14
|
+
|
15
|
+
# Basic settings
|
16
|
+
enabled: bool = Field(default=True, description="Enable {{ app_name }} functionality")
|
17
|
+
debug_mode: bool = Field(default=False, description="Enable debug mode for {{ app_name }}")
|
18
|
+
|
19
|
+
# Feature toggles
|
20
|
+
{% if features.api %}
|
21
|
+
api_enabled: bool = Field(default=True, description="Enable API endpoints")
|
22
|
+
api_rate_limit: int = Field(default=100, description="API rate limit per hour")
|
23
|
+
{% endif %}
|
24
|
+
|
25
|
+
{% if features.caching %}
|
26
|
+
cache_timeout: int = Field(default=300, description="Cache timeout in seconds")
|
27
|
+
cache_key_prefix: str = Field(default="{{ app_name }}", description="Cache key prefix")
|
28
|
+
{% endif %}
|
29
|
+
|
30
|
+
{% if features.notifications %}
|
31
|
+
notifications_enabled: bool = Field(default=True, description="Enable notifications")
|
32
|
+
email_notifications: bool = Field(default=False, description="Send email notifications")
|
33
|
+
{% endif %}
|
34
|
+
|
35
|
+
# Business logic settings
|
36
|
+
max_items_per_user: Optional[int] = Field(default=None, description="Maximum items per user")
|
37
|
+
allowed_file_types: List[str] = Field(
|
38
|
+
default=["jpg", "png", "pdf"],
|
39
|
+
description="Allowed file upload types"
|
40
|
+
)
|
41
|
+
|
42
|
+
class Meta:
|
43
|
+
app_name = "{{ app_name }}"
|
44
|
+
config_prefix = "{{ app_name|upper }}"
|
@@ -0,0 +1,81 @@
|
|
1
|
+
"""
|
2
|
+
Django-CFG module for {{ app_name }} application.
|
3
|
+
|
4
|
+
{{ description }}
|
5
|
+
"""
|
6
|
+
|
7
|
+
from django_cfg.modules import BaseCfgModule
|
8
|
+
from django_cfg.decorators import cfg_module
|
9
|
+
from .config import {{ app_name|pascal_case }}Config
|
10
|
+
|
11
|
+
|
12
|
+
@cfg_module
|
13
|
+
class {{ app_name|pascal_case }}Module(BaseCfgModule[{{ app_name|pascal_case }}Config]):
|
14
|
+
"""Django-CFG module for {{ app_name }}."""
|
15
|
+
|
16
|
+
config_class = {{ app_name|pascal_case }}Config
|
17
|
+
|
18
|
+
def __init__(self):
|
19
|
+
"""Initialize {{ app_name }} module."""
|
20
|
+
super().__init__()
|
21
|
+
self.name = "{{ app_name }}"
|
22
|
+
self.version = "1.0.0"
|
23
|
+
self.description = "{{ description }}"
|
24
|
+
|
25
|
+
async def initialize(self):
|
26
|
+
"""Initialize module resources."""
|
27
|
+
self.logger.info(f"Initializing {{ app_name }} module")
|
28
|
+
|
29
|
+
{% if features.database_setup %}
|
30
|
+
# Setup database connections if needed
|
31
|
+
await self._setup_database()
|
32
|
+
{% endif %}
|
33
|
+
|
34
|
+
{% if features.cache_setup %}
|
35
|
+
# Setup cache if needed
|
36
|
+
await self._setup_cache()
|
37
|
+
{% endif %}
|
38
|
+
|
39
|
+
self.logger.info(f"{{ app_name|title_case }} module initialized successfully")
|
40
|
+
|
41
|
+
async def cleanup(self):
|
42
|
+
"""Cleanup module resources."""
|
43
|
+
self.logger.info(f"Cleaning up {{ app_name }} module")
|
44
|
+
|
45
|
+
{% if features.cleanup_tasks %}
|
46
|
+
# Perform cleanup tasks
|
47
|
+
await self._cleanup_resources()
|
48
|
+
{% endif %}
|
49
|
+
|
50
|
+
def get_health_status(self) -> dict:
|
51
|
+
"""Get module health status."""
|
52
|
+
return {
|
53
|
+
"status": "healthy",
|
54
|
+
"module": self.name,
|
55
|
+
"version": self.version,
|
56
|
+
"config_loaded": self.config is not None,
|
57
|
+
{% if features.database_setup %}
|
58
|
+
"database_connected": self._check_database_connection(),
|
59
|
+
{% endif %}
|
60
|
+
}
|
61
|
+
|
62
|
+
{% if features.database_setup %}
|
63
|
+
async def _setup_database(self):
|
64
|
+
"""Setup database connections."""
|
65
|
+
# Implement database setup logic
|
66
|
+
pass
|
67
|
+
{% endif %}
|
68
|
+
|
69
|
+
{% if features.cache_setup %}
|
70
|
+
async def _setup_cache(self):
|
71
|
+
"""Setup cache connections."""
|
72
|
+
# Implement cache setup logic
|
73
|
+
pass
|
74
|
+
{% endif %}
|
75
|
+
|
76
|
+
{% if features.cleanup_tasks %}
|
77
|
+
async def _cleanup_resources(self):
|
78
|
+
"""Cleanup module resources."""
|
79
|
+
# Implement cleanup logic
|
80
|
+
pass
|
81
|
+
{% endif %}
|
@@ -0,0 +1,107 @@
|
|
1
|
+
"""
|
2
|
+
Forms for {{ app_name }} application.
|
3
|
+
|
4
|
+
{{ description }}
|
5
|
+
"""
|
6
|
+
|
7
|
+
from django import forms
|
8
|
+
from django.core.exceptions import ValidationError
|
9
|
+
{% if features.crispy_forms %}
|
10
|
+
from crispy_forms.helper import FormHelper
|
11
|
+
from crispy_forms.layout import Layout, Submit, Row, Column
|
12
|
+
{% endif %}
|
13
|
+
from .models import {{ app_name|pascal_case }}Model
|
14
|
+
|
15
|
+
|
16
|
+
class {{ app_name|pascal_case }}Form(forms.ModelForm):
|
17
|
+
"""Form for {{ app_name }} model."""
|
18
|
+
|
19
|
+
class Meta:
|
20
|
+
model = {{ app_name|pascal_case }}Model
|
21
|
+
fields = [
|
22
|
+
'name',
|
23
|
+
'description',
|
24
|
+
{% if features.status_tracking %}'status',{% endif %}
|
25
|
+
]
|
26
|
+
widgets = {
|
27
|
+
'description': forms.Textarea(attrs={'rows': 4}),
|
28
|
+
{% if features.status_tracking %}
|
29
|
+
'status': forms.Select(attrs={'class': 'form-select'}),
|
30
|
+
{% endif %}
|
31
|
+
}
|
32
|
+
help_texts = {
|
33
|
+
'name': 'Enter a descriptive name for this {{ app_name|singular }}',
|
34
|
+
'description': 'Provide additional details (optional)',
|
35
|
+
}
|
36
|
+
|
37
|
+
{% if features.crispy_forms %}
|
38
|
+
def __init__(self, *args, **kwargs):
|
39
|
+
super().__init__(*args, **kwargs)
|
40
|
+
self.helper = FormHelper()
|
41
|
+
self.helper.layout = Layout(
|
42
|
+
Row(
|
43
|
+
Column('name', css_class='form-group col-md-8 mb-0'),
|
44
|
+
{% if features.status_tracking %}
|
45
|
+
Column('status', css_class='form-group col-md-4 mb-0'),
|
46
|
+
{% endif %}
|
47
|
+
css_class='form-row'
|
48
|
+
),
|
49
|
+
'description',
|
50
|
+
Submit('submit', 'Save {{ app_name|title_case }}', css_class='btn btn-primary')
|
51
|
+
)
|
52
|
+
{% endif %}
|
53
|
+
|
54
|
+
def clean_name(self):
|
55
|
+
"""Validate name field."""
|
56
|
+
name = self.cleaned_data.get('name')
|
57
|
+
if name:
|
58
|
+
# Check for duplicate names (case-insensitive)
|
59
|
+
existing = {{ app_name|pascal_case }}Model.objects.filter(
|
60
|
+
name__iexact=name
|
61
|
+
)
|
62
|
+
if self.instance.pk:
|
63
|
+
existing = existing.exclude(pk=self.instance.pk)
|
64
|
+
|
65
|
+
if existing.exists():
|
66
|
+
raise ValidationError(
|
67
|
+
f'A {{ app_name|singular }} with this name already exists.'
|
68
|
+
)
|
69
|
+
|
70
|
+
return name
|
71
|
+
|
72
|
+
def clean(self):
|
73
|
+
"""Additional form validation."""
|
74
|
+
cleaned_data = super().clean()
|
75
|
+
|
76
|
+
# Add any cross-field validation here
|
77
|
+
name = cleaned_data.get('name')
|
78
|
+
description = cleaned_data.get('description')
|
79
|
+
|
80
|
+
if name and description and name.lower() in description.lower():
|
81
|
+
self.add_error('description',
|
82
|
+
'Description should not just repeat the name.')
|
83
|
+
|
84
|
+
return cleaned_data
|
85
|
+
|
86
|
+
|
87
|
+
{% if features.search_forms %}
|
88
|
+
class {{ app_name|pascal_case }}SearchForm(forms.Form):
|
89
|
+
"""Search form for {{ app_name }}."""
|
90
|
+
|
91
|
+
query = forms.CharField(
|
92
|
+
max_length=100,
|
93
|
+
required=False,
|
94
|
+
widget=forms.TextInput(attrs={
|
95
|
+
'placeholder': 'Search {{ app_name|plural }}...',
|
96
|
+
'class': 'form-control'
|
97
|
+
})
|
98
|
+
)
|
99
|
+
|
100
|
+
{% if features.status_tracking %}
|
101
|
+
status = forms.ChoiceField(
|
102
|
+
choices=[('', 'All')] + {{ app_name|pascal_case }}Model.STATUS_CHOICES,
|
103
|
+
required=False,
|
104
|
+
widget=forms.Select(attrs={'class': 'form-select'})
|
105
|
+
)
|
106
|
+
{% endif %}
|
107
|
+
{% endif %}
|
@@ -0,0 +1,139 @@
|
|
1
|
+
"""
|
2
|
+
Models for {{ app_name }} application.
|
3
|
+
|
4
|
+
{{ description }}
|
5
|
+
"""
|
6
|
+
|
7
|
+
from django.db import models
|
8
|
+
from django.urls import reverse
|
9
|
+
from django.core.validators import MinLengthValidator, MaxLengthValidator
|
10
|
+
{% if app_type == 'django_cfg' %}
|
11
|
+
from django_cfg.models import BaseCfgModel
|
12
|
+
{% endif %}
|
13
|
+
{% if features.user_relations %}
|
14
|
+
from django.contrib.auth.models import User
|
15
|
+
{% endif %}
|
16
|
+
{% if features.uuid_primary_keys %}
|
17
|
+
import uuid
|
18
|
+
{% endif %}
|
19
|
+
|
20
|
+
|
21
|
+
{% if app_type == 'django_cfg' %}
|
22
|
+
class {{ app_name|pascal_case }}Model(BaseCfgModel):
|
23
|
+
{% else %}
|
24
|
+
class {{ app_name|pascal_case }}Model(models.Model):
|
25
|
+
{% endif %}
|
26
|
+
"""Main model for {{ app_name }} application."""
|
27
|
+
|
28
|
+
{% if features.uuid_primary_keys %}
|
29
|
+
id = models.UUIDField(
|
30
|
+
primary_key=True,
|
31
|
+
default=uuid.uuid4,
|
32
|
+
editable=False,
|
33
|
+
help_text="Unique identifier"
|
34
|
+
)
|
35
|
+
{% endif %}
|
36
|
+
|
37
|
+
name = models.CharField(
|
38
|
+
max_length=100,
|
39
|
+
validators=[MinLengthValidator(2)],
|
40
|
+
help_text="Name of the {{ app_name|singular|title_case }}"
|
41
|
+
)
|
42
|
+
|
43
|
+
description = models.TextField(
|
44
|
+
blank=True,
|
45
|
+
help_text="Detailed description"
|
46
|
+
)
|
47
|
+
|
48
|
+
{% if features.status_tracking %}
|
49
|
+
STATUS_CHOICES = [
|
50
|
+
('draft', 'Draft'),
|
51
|
+
('published', 'Published'),
|
52
|
+
('archived', 'Archived'),
|
53
|
+
]
|
54
|
+
|
55
|
+
status = models.CharField(
|
56
|
+
max_length=20,
|
57
|
+
choices=STATUS_CHOICES,
|
58
|
+
default='draft',
|
59
|
+
help_text="Current status"
|
60
|
+
)
|
61
|
+
{% endif %}
|
62
|
+
|
63
|
+
{% if features.user_relations %}
|
64
|
+
owner = models.ForeignKey(
|
65
|
+
User,
|
66
|
+
on_delete=models.CASCADE,
|
67
|
+
related_name="{{ app_name }}_owned",
|
68
|
+
help_text="Owner of this {{ app_name|singular }}"
|
69
|
+
)
|
70
|
+
{% endif %}
|
71
|
+
|
72
|
+
{% if not app_type == 'django_cfg' %}
|
73
|
+
created_at = models.DateTimeField(auto_now_add=True)
|
74
|
+
updated_at = models.DateTimeField(auto_now=True)
|
75
|
+
{% endif %}
|
76
|
+
|
77
|
+
class Meta:
|
78
|
+
verbose_name = "{{ app_name|singular|title_case }}"
|
79
|
+
verbose_name_plural = "{{ app_name|plural|title_case }}"
|
80
|
+
ordering = ['-created_at']
|
81
|
+
{% if features.database_indexes %}
|
82
|
+
indexes = [
|
83
|
+
models.Index(fields=['name']),
|
84
|
+
models.Index(fields=['created_at']),
|
85
|
+
{% if features.status_tracking %}
|
86
|
+
models.Index(fields=['status']),
|
87
|
+
{% endif %}
|
88
|
+
]
|
89
|
+
{% endif %}
|
90
|
+
|
91
|
+
def __str__(self):
|
92
|
+
return self.name
|
93
|
+
|
94
|
+
def get_absolute_url(self):
|
95
|
+
return reverse('{{ app_name }}:detail', kwargs={'pk': self.pk})
|
96
|
+
|
97
|
+
{% if features.custom_methods %}
|
98
|
+
def is_published(self):
|
99
|
+
"""Check if the item is published."""
|
100
|
+
{% if features.status_tracking %}
|
101
|
+
return self.status == 'published'
|
102
|
+
{% else %}
|
103
|
+
return True
|
104
|
+
{% endif %}
|
105
|
+
|
106
|
+
def get_display_name(self):
|
107
|
+
"""Get formatted display name."""
|
108
|
+
return self.name.title()
|
109
|
+
{% endif %}
|
110
|
+
|
111
|
+
|
112
|
+
{% if features.related_models %}
|
113
|
+
class {{ app_name|pascal_case }}Category(models.Model):
|
114
|
+
"""Category model for {{ app_name }}."""
|
115
|
+
|
116
|
+
name = models.CharField(max_length=50, unique=True)
|
117
|
+
slug = models.SlugField(unique=True)
|
118
|
+
description = models.TextField(blank=True)
|
119
|
+
|
120
|
+
class Meta:
|
121
|
+
verbose_name_plural = "Categories"
|
122
|
+
ordering = ['name']
|
123
|
+
|
124
|
+
def __str__(self):
|
125
|
+
return self.name
|
126
|
+
|
127
|
+
|
128
|
+
class {{ app_name|pascal_case }}Tag(models.Model):
|
129
|
+
"""Tag model for {{ app_name }}."""
|
130
|
+
|
131
|
+
name = models.CharField(max_length=30, unique=True)
|
132
|
+
color = models.CharField(max_length=7, default='#007bff') # Hex color
|
133
|
+
|
134
|
+
class Meta:
|
135
|
+
ordering = ['name']
|
136
|
+
|
137
|
+
def __str__(self):
|
138
|
+
return self.name
|
139
|
+
{% endif %}
|
@@ -0,0 +1,91 @@
|
|
1
|
+
"""
|
2
|
+
DRF Serializers for {{ app_name }} application.
|
3
|
+
|
4
|
+
{{ description }}
|
5
|
+
"""
|
6
|
+
|
7
|
+
from rest_framework import serializers
|
8
|
+
{% if features.nested_serializers %}
|
9
|
+
from rest_framework.fields import SerializerMethodField
|
10
|
+
{% endif %}
|
11
|
+
from .models import {{ app_name|pascal_case }}Model
|
12
|
+
{% if features.related_models %}
|
13
|
+
from .models import {{ app_name|pascal_case }}Category, {{ app_name|pascal_case }}Tag
|
14
|
+
{% endif %}
|
15
|
+
|
16
|
+
|
17
|
+
class {{ app_name|pascal_case }}Serializer(serializers.ModelSerializer):
|
18
|
+
"""Serializer for {{ app_name }} model."""
|
19
|
+
|
20
|
+
{% if features.computed_fields %}
|
21
|
+
display_name = serializers.SerializerMethodField()
|
22
|
+
is_published = serializers.SerializerMethodField()
|
23
|
+
{% endif %}
|
24
|
+
|
25
|
+
class Meta:
|
26
|
+
model = {{ app_name|pascal_case }}Model
|
27
|
+
fields = [
|
28
|
+
'id',
|
29
|
+
'name',
|
30
|
+
'description',
|
31
|
+
{% if features.status_tracking %}'status',{% endif %}
|
32
|
+
{% if features.user_relations %}'owner',{% endif %}
|
33
|
+
'created_at',
|
34
|
+
'updated_at',
|
35
|
+
{% if features.computed_fields %}
|
36
|
+
'display_name',
|
37
|
+
'is_published',
|
38
|
+
{% endif %}
|
39
|
+
]
|
40
|
+
read_only_fields = ['id', 'created_at', 'updated_at']
|
41
|
+
|
42
|
+
{% if features.computed_fields %}
|
43
|
+
def get_display_name(self, obj):
|
44
|
+
"""Get formatted display name."""
|
45
|
+
return obj.get_display_name()
|
46
|
+
|
47
|
+
def get_is_published(self, obj):
|
48
|
+
"""Check if item is published."""
|
49
|
+
return obj.is_published()
|
50
|
+
{% endif %}
|
51
|
+
|
52
|
+
def validate_name(self, value):
|
53
|
+
"""Validate name field."""
|
54
|
+
if len(value.strip()) < 2:
|
55
|
+
raise serializers.ValidationError(
|
56
|
+
"Name must be at least 2 characters long."
|
57
|
+
)
|
58
|
+
return value.strip()
|
59
|
+
|
60
|
+
|
61
|
+
{% if features.list_serializers %}
|
62
|
+
class {{ app_name|pascal_case }}ListSerializer(serializers.ModelSerializer):
|
63
|
+
"""Lightweight serializer for {{ app_name }} lists."""
|
64
|
+
|
65
|
+
class Meta:
|
66
|
+
model = {{ app_name|pascal_case }}Model
|
67
|
+
fields = [
|
68
|
+
'id',
|
69
|
+
'name',
|
70
|
+
{% if features.status_tracking %}'status',{% endif %}
|
71
|
+
'created_at'
|
72
|
+
]
|
73
|
+
{% endif %}
|
74
|
+
|
75
|
+
|
76
|
+
{% if features.related_models %}
|
77
|
+
class {{ app_name|pascal_case }}CategorySerializer(serializers.ModelSerializer):
|
78
|
+
"""Serializer for {{ app_name }} categories."""
|
79
|
+
|
80
|
+
class Meta:
|
81
|
+
model = {{ app_name|pascal_case }}Category
|
82
|
+
fields = ['id', 'name', 'slug', 'description']
|
83
|
+
|
84
|
+
|
85
|
+
class {{ app_name|pascal_case }}TagSerializer(serializers.ModelSerializer):
|
86
|
+
"""Serializer for {{ app_name }} tags."""
|
87
|
+
|
88
|
+
class Meta:
|
89
|
+
model = {{ app_name|pascal_case }}Tag
|
90
|
+
fields = ['id', 'name', 'color']
|
91
|
+
{% endif %}
|
@@ -0,0 +1,195 @@
|
|
1
|
+
"""
|
2
|
+
Tests for {{ app_name }} application.
|
3
|
+
|
4
|
+
{{ description }}
|
5
|
+
"""
|
6
|
+
|
7
|
+
from django.test import TestCase, Client
|
8
|
+
from django.urls import reverse
|
9
|
+
{% if features.user_relations %}
|
10
|
+
from django.contrib.auth.models import User
|
11
|
+
{% endif %}
|
12
|
+
{% if features.api_tests %}
|
13
|
+
from rest_framework.test import APITestCase
|
14
|
+
from rest_framework import status
|
15
|
+
{% endif %}
|
16
|
+
from .models import {{ app_name|pascal_case }}Model
|
17
|
+
|
18
|
+
|
19
|
+
class {{ app_name|pascal_case }}ModelTest(TestCase):
|
20
|
+
"""Test cases for {{ app_name }} model."""
|
21
|
+
|
22
|
+
def setUp(self):
|
23
|
+
"""Set up test data."""
|
24
|
+
{% if features.user_relations %}
|
25
|
+
self.user = User.objects.create_user(
|
26
|
+
username='testuser',
|
27
|
+
email='test@example.com',
|
28
|
+
password='testpass123'
|
29
|
+
)
|
30
|
+
{% endif %}
|
31
|
+
|
32
|
+
self.{{ app_name|snake_case }} = {{ app_name|pascal_case }}Model.objects.create(
|
33
|
+
name='Test {{ app_name|title_case }}',
|
34
|
+
description='Test description',
|
35
|
+
{% if features.status_tracking %}status='draft',{% endif %}
|
36
|
+
{% if features.user_relations %}owner=self.user{% endif %}
|
37
|
+
)
|
38
|
+
|
39
|
+
def test_string_representation(self):
|
40
|
+
"""Test string representation of model."""
|
41
|
+
self.assertEqual(str(self.{{ app_name|snake_case }}), 'Test {{ app_name|title_case }}')
|
42
|
+
|
43
|
+
def test_get_absolute_url(self):
|
44
|
+
"""Test get_absolute_url method."""
|
45
|
+
url = self.{{ app_name|snake_case }}.get_absolute_url()
|
46
|
+
expected_url = reverse('{{ app_name }}:detail', kwargs={'pk': self.{{ app_name|snake_case }}.pk})
|
47
|
+
self.assertEqual(url, expected_url)
|
48
|
+
|
49
|
+
{% if features.custom_methods %}
|
50
|
+
def test_is_published(self):
|
51
|
+
"""Test is_published method."""
|
52
|
+
{% if features.status_tracking %}
|
53
|
+
self.assertFalse(self.{{ app_name|snake_case }}.is_published())
|
54
|
+
|
55
|
+
self.{{ app_name|snake_case }}.status = 'published'
|
56
|
+
self.{{ app_name|snake_case }}.save()
|
57
|
+
self.assertTrue(self.{{ app_name|snake_case }}.is_published())
|
58
|
+
{% else %}
|
59
|
+
self.assertTrue(self.{{ app_name|snake_case }}.is_published())
|
60
|
+
{% endif %}
|
61
|
+
|
62
|
+
def test_get_display_name(self):
|
63
|
+
"""Test get_display_name method."""
|
64
|
+
display_name = self.{{ app_name|snake_case }}.get_display_name()
|
65
|
+
self.assertEqual(display_name, 'Test {{ app_name|title_case }}')
|
66
|
+
{% endif %}
|
67
|
+
|
68
|
+
|
69
|
+
{% if features.view_tests %}
|
70
|
+
class {{ app_name|pascal_case }}ViewTest(TestCase):
|
71
|
+
"""Test cases for {{ app_name }} views."""
|
72
|
+
|
73
|
+
def setUp(self):
|
74
|
+
"""Set up test data."""
|
75
|
+
self.client = Client()
|
76
|
+
{% if features.user_relations %}
|
77
|
+
self.user = User.objects.create_user(
|
78
|
+
username='testuser',
|
79
|
+
email='test@example.com',
|
80
|
+
password='testpass123'
|
81
|
+
)
|
82
|
+
{% endif %}
|
83
|
+
|
84
|
+
self.{{ app_name|snake_case }} = {{ app_name|pascal_case }}Model.objects.create(
|
85
|
+
name='Test {{ app_name|title_case }}',
|
86
|
+
description='Test description',
|
87
|
+
{% if features.status_tracking %}status='published',{% endif %}
|
88
|
+
{% if features.user_relations %}owner=self.user{% endif %}
|
89
|
+
)
|
90
|
+
|
91
|
+
{% if features.function_based_views %}
|
92
|
+
def test_index_view(self):
|
93
|
+
"""Test index view."""
|
94
|
+
{% if features.authentication %}
|
95
|
+
self.client.login(username='testuser', password='testpass123')
|
96
|
+
{% endif %}
|
97
|
+
|
98
|
+
url = reverse('{{ app_name }}:index')
|
99
|
+
response = self.client.get(url)
|
100
|
+
|
101
|
+
self.assertEqual(response.status_code, 200)
|
102
|
+
self.assertContains(response, 'Test {{ app_name|title_case }}')
|
103
|
+
|
104
|
+
def test_detail_view(self):
|
105
|
+
"""Test detail view."""
|
106
|
+
{% if features.authentication %}
|
107
|
+
self.client.login(username='testuser', password='testpass123')
|
108
|
+
{% endif %}
|
109
|
+
|
110
|
+
url = reverse('{{ app_name }}:detail', kwargs={'pk': self.{{ app_name|snake_case }}.pk})
|
111
|
+
response = self.client.get(url)
|
112
|
+
|
113
|
+
self.assertEqual(response.status_code, 200)
|
114
|
+
self.assertContains(response, self.{{ app_name|snake_case }}.name)
|
115
|
+
{% endif %}
|
116
|
+
|
117
|
+
{% if features.class_based_views %}
|
118
|
+
def test_list_view(self):
|
119
|
+
"""Test list view."""
|
120
|
+
{% if features.authentication %}
|
121
|
+
self.client.login(username='testuser', password='testpass123')
|
122
|
+
{% endif %}
|
123
|
+
|
124
|
+
url = reverse('{{ app_name }}:list')
|
125
|
+
response = self.client.get(url)
|
126
|
+
|
127
|
+
self.assertEqual(response.status_code, 200)
|
128
|
+
self.assertContains(response, self.{{ app_name|snake_case }}.name)
|
129
|
+
{% endif %}
|
130
|
+
|
131
|
+
{% if features.crud_views %}
|
132
|
+
def test_create_view(self):
|
133
|
+
"""Test create view."""
|
134
|
+
{% if features.authentication %}
|
135
|
+
self.client.login(username='testuser', password='testpass123')
|
136
|
+
{% endif %}
|
137
|
+
|
138
|
+
url = reverse('{{ app_name }}:create')
|
139
|
+
|
140
|
+
# Test GET request
|
141
|
+
response = self.client.get(url)
|
142
|
+
self.assertEqual(response.status_code, 200)
|
143
|
+
|
144
|
+
# Test POST request
|
145
|
+
data = {
|
146
|
+
'name': 'New {{ app_name|title_case }}',
|
147
|
+
'description': 'New description',
|
148
|
+
{% if features.status_tracking %}'status': 'draft'{% endif %}
|
149
|
+
}
|
150
|
+
response = self.client.post(url, data)
|
151
|
+
self.assertEqual(response.status_code, 302) # Redirect after success
|
152
|
+
|
153
|
+
# Verify object was created
|
154
|
+
self.assertTrue(
|
155
|
+
{{ app_name|pascal_case }}Model.objects.filter(name='New {{ app_name|title_case }}').exists()
|
156
|
+
)
|
157
|
+
{% endif %}
|
158
|
+
{% endif %}
|
159
|
+
|
160
|
+
|
161
|
+
{% if features.api_tests %}
|
162
|
+
class {{ app_name|pascal_case }}APITest(APITestCase):
|
163
|
+
"""Test cases for {{ app_name }} API."""
|
164
|
+
|
165
|
+
def setUp(self):
|
166
|
+
"""Set up test data."""
|
167
|
+
{% if features.user_relations %}
|
168
|
+
self.user = User.objects.create_user(
|
169
|
+
username='testuser',
|
170
|
+
email='test@example.com',
|
171
|
+
password='testpass123'
|
172
|
+
)
|
173
|
+
{% endif %}
|
174
|
+
|
175
|
+
self.{{ app_name|snake_case }} = {{ app_name|pascal_case }}Model.objects.create(
|
176
|
+
name='Test {{ app_name|title_case }}',
|
177
|
+
description='Test description',
|
178
|
+
{% if features.status_tracking %}status='published',{% endif %}
|
179
|
+
{% if features.user_relations %}owner=self.user{% endif %}
|
180
|
+
)
|
181
|
+
|
182
|
+
def test_api_view(self):
|
183
|
+
"""Test API view."""
|
184
|
+
{% if features.authentication %}
|
185
|
+
self.client.force_authenticate(user=self.user)
|
186
|
+
{% endif %}
|
187
|
+
|
188
|
+
url = reverse('{{ app_name }}:api')
|
189
|
+
response = self.client.get(url)
|
190
|
+
|
191
|
+
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
192
|
+
self.assertTrue(response.data['success'])
|
193
|
+
self.assertEqual(len(response.data['data']), 1)
|
194
|
+
self.assertEqual(response.data['data'][0]['name'], 'Test {{ app_name|title_case }}')
|
195
|
+
{% endif %}
|
@@ -0,0 +1,35 @@
|
|
1
|
+
"""
|
2
|
+
URL configuration for {{ app_name }} application.
|
3
|
+
|
4
|
+
{{ description }}
|
5
|
+
"""
|
6
|
+
|
7
|
+
from django.urls import path, include
|
8
|
+
{% if features.api_views %}
|
9
|
+
from django.urls import re_path
|
10
|
+
{% endif %}
|
11
|
+
from . import views
|
12
|
+
|
13
|
+
app_name = '{{ app_name }}'
|
14
|
+
|
15
|
+
urlpatterns = [
|
16
|
+
{% if features.function_based_views %}
|
17
|
+
path('', views.{{ app_name }}_index, name='index'),
|
18
|
+
path('<int:pk>/', views.{{ app_name }}_detail, name='detail'),
|
19
|
+
{% endif %}
|
20
|
+
|
21
|
+
{% if features.class_based_views %}
|
22
|
+
path('list/', views.{{ app_name|pascal_case }}ListView.as_view(), name='list'),
|
23
|
+
path('detail/<int:pk>/', views.{{ app_name|pascal_case }}DetailView.as_view(), name='detail'),
|
24
|
+
|
25
|
+
{% if features.crud_views %}
|
26
|
+
path('create/', views.{{ app_name|pascal_case }}CreateView.as_view(), name='create'),
|
27
|
+
path('update/<int:pk>/', views.{{ app_name|pascal_case }}UpdateView.as_view(), name='update'),
|
28
|
+
path('delete/<int:pk>/', views.{{ app_name|pascal_case }}DeleteView.as_view(), name='delete'),
|
29
|
+
{% endif %}
|
30
|
+
{% endif %}
|
31
|
+
|
32
|
+
{% if features.api_views %}
|
33
|
+
path('api/', views.{{ app_name|pascal_case }}APIView.as_view(), name='api'),
|
34
|
+
{% endif %}
|
35
|
+
]
|