codex-django-cli 0.2.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.
- codex_django_cli/__init__.py +12 -0
- codex_django_cli/blueprints/apps/default/__init__.py +0 -0
- codex_django_cli/blueprints/apps/default/admin/__init__.py +0 -0
- codex_django_cli/blueprints/apps/default/apps.py.j2 +0 -0
- codex_django_cli/blueprints/apps/default/forms/__init__.py +0 -0
- codex_django_cli/blueprints/apps/default/models/__init__.py +0 -0
- codex_django_cli/blueprints/apps/default/modules/__init__.py +0 -0
- codex_django_cli/blueprints/apps/default/selector/__init__.py +0 -0
- codex_django_cli/blueprints/apps/default/services/__init__.py +0 -0
- codex_django_cli/blueprints/apps/default/tests/__init__.py +0 -0
- codex_django_cli/blueprints/apps/default/translations.py.j2 +0 -0
- codex_django_cli/blueprints/apps/default/urls.py.j2 +0 -0
- codex_django_cli/blueprints/apps/default/views/__init__.py +0 -0
- codex_django_cli/blueprints/deploy/shared/.dockerignore.j2 +24 -0
- codex_django_cli/blueprints/deploy/shared/.env.example.j2 +64 -0
- codex_django_cli/blueprints/deploy/shared/backend/Dockerfile.j2 +36 -0
- codex_django_cli/blueprints/deploy/shared/backend/entrypoint.sh.j2 +20 -0
- codex_django_cli/blueprints/deploy/shared/nginx/Dockerfile.local.j2 +14 -0
- codex_django_cli/blueprints/deploy/shared/nginx/nginx-main.conf.j2 +67 -0
- codex_django_cli/blueprints/deploy/shared/nginx/site-local.conf.j2 +66 -0
- codex_django_cli/blueprints/deploy/shared/worker/Dockerfile.j2 +25 -0
- codex_django_cli/blueprints/deploy/stack/docker/base.Dockerfile.j2 +38 -0
- codex_django_cli/blueprints/deploy/stack/docker/django.Dockerfile.j2 +27 -0
- codex_django_cli/blueprints/deploy/stack/docker/entrypoint.sh.j2 +19 -0
- codex_django_cli/blueprints/deploy/stack/docker-compose.apps.yml.j2 +41 -0
- codex_django_cli/blueprints/deploy/stack/docker-compose.infra.yml.j2 +80 -0
- codex_django_cli/blueprints/deploy/stack/docker-compose.local.apps.yml.j2 +41 -0
- codex_django_cli/blueprints/deploy/stack/docker-compose.local.infra.yml.j2 +94 -0
- codex_django_cli/blueprints/deploy/stack/docker-compose.test.yml.j2 +63 -0
- codex_django_cli/blueprints/deploy/stack/nginx/Dockerfile.j2 +12 -0
- codex_django_cli/blueprints/deploy/stack/nginx/conf.d/default.conf.j2 +68 -0
- codex_django_cli/blueprints/deploy/stack/nginx/site.conf.template.j2 +81 -0
- codex_django_cli/blueprints/deploy/stack_workflows/ci-develop.yml.j2 +42 -0
- codex_django_cli/blueprints/deploy/stack_workflows/ci-main.yml.j2 +165 -0
- codex_django_cli/blueprints/deploy/stack_workflows/deploy-cluster.yml.j2 +112 -0
- codex_django_cli/blueprints/deploy/standalone/docker-compose.prod.yml.j2 +118 -0
- codex_django_cli/blueprints/deploy/standalone/docker-compose.test.yml.j2 +86 -0
- codex_django_cli/blueprints/deploy/standalone/docker-compose.yml.j2 +151 -0
- codex_django_cli/blueprints/deploy/standalone/nginx/Dockerfile.j2 +18 -0
- codex_django_cli/blueprints/deploy/standalone/nginx/site.conf.template.j2 +168 -0
- codex_django_cli/blueprints/deploy/standalone_workflows/ci-develop.yml.j2 +42 -0
- codex_django_cli/blueprints/deploy/standalone_workflows/ci-main.yml.j2 +113 -0
- codex_django_cli/blueprints/deploy/standalone_workflows/deploy-production-tag.yml.j2 +211 -0
- codex_django_cli/blueprints/features/booking/booking/__init__.py.j2 +0 -0
- codex_django_cli/blueprints/features/booking/booking/admin.py.j2 +52 -0
- codex_django_cli/blueprints/features/booking/booking/apps.py.j2 +8 -0
- codex_django_cli/blueprints/features/booking/booking/models.py.j2 +142 -0
- codex_django_cli/blueprints/features/booking/booking/selectors.py.j2 +102 -0
- codex_django_cli/blueprints/features/booking/booking/urls.py.j2 +12 -0
- codex_django_cli/blueprints/features/booking/booking/views.py.j2 +174 -0
- codex_django_cli/blueprints/features/booking/booking/wiki.md.j2 +142 -0
- codex_django_cli/blueprints/features/booking/cabinet/templates/cabinet/booking/my_bookings.html +249 -0
- codex_django_cli/blueprints/features/booking/cabinet/views/booking.py.j2 +70 -0
- codex_django_cli/blueprints/features/booking/system/admin/booking_settings.py.j2 +31 -0
- codex_django_cli/blueprints/features/booking/system/models/booking_settings.py.j2 +7 -0
- codex_django_cli/blueprints/features/booking/templates/booking/booking_page.html +137 -0
- codex_django_cli/blueprints/features/booking/templates/booking/partials/step_confirm.html +143 -0
- codex_django_cli/blueprints/features/booking/templates/booking/partials/step_date.html +184 -0
- codex_django_cli/blueprints/features/booking/templates/booking/partials/step_service.html +78 -0
- codex_django_cli/blueprints/features/booking/templates/booking/partials/step_time.html +89 -0
- codex_django_cli/blueprints/features/client_cabinet/cabinet/adapters.py.j2 +21 -0
- codex_django_cli/blueprints/features/client_cabinet/cabinet/templates/cabinet/client/my_appointments.html +58 -0
- codex_django_cli/blueprints/features/client_cabinet/cabinet/templates/cabinet/client/profile.html +107 -0
- codex_django_cli/blueprints/features/client_cabinet/cabinet/templates/cabinet/client/settings.html +106 -0
- codex_django_cli/blueprints/features/client_cabinet/cabinet/templates/cabinet/client/settings_notifications.html +106 -0
- codex_django_cli/blueprints/features/client_cabinet/cabinet/templates/cabinet/client/settings_privacy.html +135 -0
- codex_django_cli/blueprints/features/client_cabinet/cabinet/views/client.py.j2 +49 -0
- codex_django_cli/blueprints/features/client_cabinet/system/models/user_profile.py.j2 +22 -0
- codex_django_cli/blueprints/features/notifications/arq/client.j2 +22 -0
- codex_django_cli/blueprints/features/notifications/feature/models/email_content.j2 +15 -0
- codex_django_cli/blueprints/features/notifications/feature/selectors/email_content.j2 +23 -0
- codex_django_cli/blueprints/features/notifications/feature/services/notification.j2 +66 -0
- codex_django_cli/blueprints/project/cabinet/__init__.py +0 -0
- codex_django_cli/blueprints/project/cabinet/admin/__init__.py +0 -0
- codex_django_cli/blueprints/project/cabinet/apps.py.j2 +11 -0
- codex_django_cli/blueprints/project/cabinet/cabinet.py.j2 +33 -0
- codex_django_cli/blueprints/project/cabinet/forms/__init__.py +0 -0
- codex_django_cli/blueprints/project/cabinet/mock.py.j2 +110 -0
- codex_django_cli/blueprints/project/cabinet/models/__init__.py +0 -0
- codex_django_cli/blueprints/project/cabinet/modules/__init__.py +0 -0
- codex_django_cli/blueprints/project/cabinet/selector/__init__.py +3 -0
- codex_django_cli/blueprints/project/cabinet/selector/users.py.j2 +25 -0
- codex_django_cli/blueprints/project/cabinet/services/__init__.py +0 -0
- codex_django_cli/blueprints/project/cabinet/static/cabinet/css/base.css +11 -0
- codex_django_cli/blueprints/project/cabinet/static/cabinet/css/compiler_config.json +5 -0
- codex_django_cli/blueprints/project/cabinet/static/cabinet/css/theme/tokens.css +30 -0
- codex_django_cli/blueprints/project/cabinet/static/cabinet/js/app/cabinet.js +37 -0
- codex_django_cli/blueprints/project/cabinet/static/cabinet/js/compiler_config.json +7 -0
- codex_django_cli/blueprints/project/cabinet/templates/cabinet/users/detail.html +91 -0
- codex_django_cli/blueprints/project/cabinet/templates/cabinet/users/index.html +97 -0
- codex_django_cli/blueprints/project/cabinet/tests/__init__.py +0 -0
- codex_django_cli/blueprints/project/cabinet/translations.py.j2 +2 -0
- codex_django_cli/blueprints/project/cabinet/urls.py.j2 +22 -0
- codex_django_cli/blueprints/project/cabinet/views/__init__.py +3 -0
- codex_django_cli/blueprints/project/cabinet/views/users.py.j2 +17 -0
- codex_django_cli/blueprints/project/core/__init__.py.j2 +1 -0
- codex_django_cli/blueprints/project/core/apps.py.j2 +15 -0
- codex_django_cli/blueprints/project/core/asgi.py.j2 +7 -0
- codex_django_cli/blueprints/project/core/logger.py.j2 +57 -0
- codex_django_cli/blueprints/project/core/redis.py.j2 +4 -0
- codex_django_cli/blueprints/project/core/settings/__init__.py.j2 +4 -0
- codex_django_cli/blueprints/project/core/settings/base.py.j2 +67 -0
- codex_django_cli/blueprints/project/core/settings/dev.py.j2 +56 -0
- codex_django_cli/blueprints/project/core/settings/modules/__init__.py.j2 +1 -0
- codex_django_cli/blueprints/project/core/settings/modules/admin.py.j2 +72 -0
- codex_django_cli/blueprints/project/core/settings/modules/apps.py.j2 +64 -0
- codex_django_cli/blueprints/project/core/settings/modules/cache.py.j2 +49 -0
- codex_django_cli/blueprints/project/core/settings/modules/codex.py.j2 +39 -0
- codex_django_cli/blueprints/project/core/settings/modules/database.py.j2 +49 -0
- codex_django_cli/blueprints/project/core/settings/modules/internationalization.py.j2 +43 -0
- codex_django_cli/blueprints/project/core/settings/modules/logging.py.j2 +45 -0
- codex_django_cli/blueprints/project/core/settings/modules/middleware.py.j2 +17 -0
- codex_django_cli/blueprints/project/core/settings/modules/security.py.j2 +53 -0
- codex_django_cli/blueprints/project/core/settings/modules/sitemap.py.j2 +14 -0
- codex_django_cli/blueprints/project/core/settings/modules/static.py.j2 +36 -0
- codex_django_cli/blueprints/project/core/settings/modules/templates.py.j2 +29 -0
- codex_django_cli/blueprints/project/core/settings/prod.py.j2 +77 -0
- codex_django_cli/blueprints/project/core/settings/test.py.j2 +40 -0
- codex_django_cli/blueprints/project/core/sitemaps.py.j2 +26 -0
- codex_django_cli/blueprints/project/core/urls.py.j2 +71 -0
- codex_django_cli/blueprints/project/core/wsgi.py.j2 +7 -0
- codex_django_cli/blueprints/project/features/__init__.py.j2 +0 -0
- codex_django_cli/blueprints/project/features/main/admin/__init__.py +0 -0
- codex_django_cli/blueprints/project/features/main/apps.py.j2 +8 -0
- codex_django_cli/blueprints/project/features/main/forms/__init__.py +0 -0
- codex_django_cli/blueprints/project/features/main/models/__init__.py +0 -0
- codex_django_cli/blueprints/project/features/main/sitemaps.py.j2 +23 -0
- codex_django_cli/blueprints/project/features/main/tests/__init__.py +0 -0
- codex_django_cli/blueprints/project/features/main/translations.py.j2 +2 -0
- codex_django_cli/blueprints/project/features/main/urls.py.j2 +8 -0
- codex_django_cli/blueprints/project/features/main/views/__init__.py.j2 +9 -0
- codex_django_cli/blueprints/project/manage.py.j2 +39 -0
- codex_django_cli/blueprints/project/static/css/base/components.css +88 -0
- codex_django_cli/blueprints/project/static/css/base/footer.css +43 -0
- codex_django_cli/blueprints/project/static/css/base/header.css +76 -0
- codex_django_cli/blueprints/project/static/css/base/layout.css +58 -0
- codex_django_cli/blueprints/project/static/css/base/reset.css +65 -0
- codex_django_cli/blueprints/project/static/css/base/tokens.css +45 -0
- codex_django_cli/blueprints/project/static/css/base.css +31 -0
- codex_django_cli/blueprints/project/static/css/compiler_config.json +10 -0
- codex_django_cli/blueprints/project/static/css/pages/contacts.css +42 -0
- codex_django_cli/blueprints/project/static/css/pages/errors.css +11 -0
- codex_django_cli/blueprints/project/static/css/pages/home.css +120 -0
- codex_django_cli/blueprints/project/static/js/app/main.js +8 -0
- codex_django_cli/blueprints/project/static/js/vendor/alpine.min.js +9 -0
- codex_django_cli/blueprints/project/static/js/vendor/htmx.min.js +9 -0
- codex_django_cli/blueprints/project/static/manifest.json +15 -0
- codex_django_cli/blueprints/project/static/robots.txt +4 -0
- codex_django_cli/blueprints/project/system/__init__.py.j2 +1 -0
- codex_django_cli/blueprints/project/system/admin/__init__.py.j2 +15 -0
- codex_django_cli/blueprints/project/system/admin/seo.py.j2 +28 -0
- codex_django_cli/blueprints/project/system/admin/settings.py.j2 +65 -0
- codex_django_cli/blueprints/project/system/admin/static.py.j2 +18 -0
- codex_django_cli/blueprints/project/system/apps.py.j2 +9 -0
- codex_django_cli/blueprints/project/system/forms/__init__.py.j2 +1 -0
- codex_django_cli/blueprints/project/system/management/__init__.py +0 -0
- codex_django_cli/blueprints/project/system/management/commands/__init__.py +0 -0
- codex_django_cli/blueprints/project/system/management/commands/dev.py.j2 +5 -0
- codex_django_cli/blueprints/project/system/management/commands/menu.py.j2 +81 -0
- codex_django_cli/blueprints/project/system/management/commands/runserver_plus.py.j2 +46 -0
- codex_django_cli/blueprints/project/system/management/commands/update_all_content.py.j2 +17 -0
- codex_django_cli/blueprints/project/system/management/commands/update_site_settings.py.j2 +80 -0
- codex_django_cli/blueprints/project/system/models/__init__.py.j2 +15 -0
- codex_django_cli/blueprints/project/system/models/seo.py.j2 +37 -0
- codex_django_cli/blueprints/project/system/models/settings.py.j2 +31 -0
- codex_django_cli/blueprints/project/system/models/static.py.j2 +13 -0
- codex_django_cli/blueprints/project/system/services/__init__.py.j2 +1 -0
- codex_django_cli/blueprints/project/system/urls.py.j2 +7 -0
- codex_django_cli/blueprints/project/system/views/__init__.py.j2 +1 -0
- codex_django_cli/blueprints/project/system/views/errors.py.j2 +13 -0
- codex_django_cli/blueprints/project/templates/base.html.j2 +53 -0
- codex_django_cli/blueprints/project/templates/errors/400.html +9 -0
- codex_django_cli/blueprints/project/templates/errors/403.html +9 -0
- codex_django_cli/blueprints/project/templates/errors/404.html +16 -0
- codex_django_cli/blueprints/project/templates/errors/500.html +16 -0
- codex_django_cli/blueprints/project/templates/includes/_analytics_body.html +2 -0
- codex_django_cli/blueprints/project/templates/includes/_analytics_head.html +2 -0
- codex_django_cli/blueprints/project/templates/includes/_cookie_consent.html +2 -0
- codex_django_cli/blueprints/project/templates/includes/_critical_css.html +38 -0
- codex_django_cli/blueprints/project/templates/includes/_footer.html +57 -0
- codex_django_cli/blueprints/project/templates/includes/_header.html.j2 +75 -0
- codex_django_cli/blueprints/project/templates/includes/_hreflang_tags.html.j2 +11 -0
- codex_django_cli/blueprints/project/templates/includes/_meta.html +44 -0
- codex_django_cli/blueprints/project/templates/main/contacts.html +38 -0
- codex_django_cli/blueprints/project/templates/main/home.html +128 -0
- codex_django_cli/blueprints/project/templates/main/home.html.j2 +129 -0
- codex_django_cli/blueprints/project/templates/sitemap.xml +16 -0
- codex_django_cli/blueprints/repo/.env.example.j2 +15 -0
- codex_django_cli/blueprints/repo/.github/workflows/.gitkeep +1 -0
- codex_django_cli/blueprints/repo/.gitignore +38 -0
- codex_django_cli/blueprints/repo/README.md.j2 +32 -0
- codex_django_cli/blueprints/repo/docs/README.md +5 -0
- codex_django_cli/blueprints/repo/pyproject.toml.j2 +46 -0
- codex_django_cli/blueprints/repo/tools/dev/check.py.j2 +23 -0
- codex_django_cli/blueprints/repo/tools/dev/generate_project_tree.py +15 -0
- codex_django_cli/commands/__init__.py +1 -0
- codex_django_cli/commands/add_app.py +56 -0
- codex_django_cli/commands/booking.py +92 -0
- codex_django_cli/commands/client_cabinet.py +66 -0
- codex_django_cli/commands/deploy.py +96 -0
- codex_django_cli/commands/init.py +216 -0
- codex_django_cli/commands/notifications.py +59 -0
- codex_django_cli/commands/quality.py +116 -0
- codex_django_cli/engine.py +113 -0
- codex_django_cli/main.py +470 -0
- codex_django_cli/prompts.py +258 -0
- codex_django_cli/py.typed +0 -0
- codex_django_cli/utils.py +25 -0
- codex_django_cli-0.2.0.dist-info/METADATA +66 -0
- codex_django_cli-0.2.0.dist-info/RECORD +212 -0
- codex_django_cli-0.2.0.dist-info/WHEEL +4 -0
- codex_django_cli-0.2.0.dist-info/entry_points.txt +2 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import TYPE_CHECKING, Union
|
|
3
|
+
|
|
4
|
+
from django.conf import settings
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from loguru import Logger
|
|
8
|
+
|
|
9
|
+
# Declare logger with a Union type to satisfy mypy
|
|
10
|
+
logger: Union[logging.Logger, "Logger"]
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
from codex_core.common.loguru_setup import setup_logging
|
|
14
|
+
from loguru import logger as loguru_logger
|
|
15
|
+
|
|
16
|
+
logger = loguru_logger
|
|
17
|
+
LOGURU_AVAILABLE = True
|
|
18
|
+
except ImportError:
|
|
19
|
+
logger = logging.getLogger(__name__)
|
|
20
|
+
LOGURU_AVAILABLE = False
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class DjangoLoggingSettingsAdapter:
|
|
24
|
+
"""Adapts Django settings to codex-core LoggingSettingsProtocol."""
|
|
25
|
+
|
|
26
|
+
def __init__(self) -> None:
|
|
27
|
+
self.log_level_console = getattr(settings, "LOG_LEVEL_CONSOLE", "INFO")
|
|
28
|
+
self.log_level_file = getattr(settings, "LOG_LEVEL_FILE", "DEBUG")
|
|
29
|
+
self.log_rotation = getattr(settings, "LOG_ROTATION", "10 MB")
|
|
30
|
+
self.log_dir = getattr(settings, "LOG_DIR", "logs")
|
|
31
|
+
self.debug = getattr(settings, "DEBUG", False)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def init_logging() -> None:
|
|
35
|
+
"""Initialize logging based on project settings and available libraries."""
|
|
36
|
+
if not LOGURU_AVAILABLE:
|
|
37
|
+
# Fallback to standard Django LOGGING already configured in settings
|
|
38
|
+
if isinstance(logger, logging.Logger):
|
|
39
|
+
logger.info("Loguru or codex-core not found. Using standard Django logging.")
|
|
40
|
+
return
|
|
41
|
+
|
|
42
|
+
# Use codex-core setup
|
|
43
|
+
service_name = getattr(settings, "PROJECT_NAME", "django-backend")
|
|
44
|
+
adapter = DjangoLoggingSettingsAdapter()
|
|
45
|
+
|
|
46
|
+
setup_logging(
|
|
47
|
+
settings=adapter,
|
|
48
|
+
service_name=service_name,
|
|
49
|
+
intercept_loggers=["django", "django.server", "django.db.backends"],
|
|
50
|
+
log_levels={
|
|
51
|
+
"django.db.backends": logging.WARNING,
|
|
52
|
+
"django.utils.autoreload": logging.WARNING,
|
|
53
|
+
},
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
if not isinstance(logger, logging.Logger):
|
|
57
|
+
logger.info(f"Loguru initialized via codex-core for {service_name}")
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Cloud-Native Django Settings.
|
|
3
|
+
Supports layered configuration: Environment Variables > Project .env > Common .env.
|
|
4
|
+
Ready for Docker Compose, Swarm, and Kubernetes.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
from dotenv import load_dotenv
|
|
11
|
+
|
|
12
|
+
# ═══════════════════════════════════════════
|
|
13
|
+
# Paths & Project Identity
|
|
14
|
+
# ═══════════════════════════════════════════
|
|
15
|
+
|
|
16
|
+
# Root of Django project (where manage.py is)
|
|
17
|
+
BASE_DIR = Path(__file__).resolve().parent.parent.parent
|
|
18
|
+
|
|
19
|
+
# 1. Try to load Common .env (Infrastructure level)
|
|
20
|
+
# Path can be overridden via ENV_COMMON_PATH for Swarm/K8s
|
|
21
|
+
common_env = os.environ.get("ENV_COMMON_PATH")
|
|
22
|
+
if common_env and os.path.exists(common_env):
|
|
23
|
+
load_dotenv(common_env)
|
|
24
|
+
else:
|
|
25
|
+
# Fallback for local dev: look 2 levels up
|
|
26
|
+
load_dotenv(BASE_DIR.parent.parent / ".env")
|
|
27
|
+
|
|
28
|
+
# 2. Try to load Project-specific .env
|
|
29
|
+
# override=True ensures project settings take precedence
|
|
30
|
+
project_env = os.environ.get("ENV_PROJECT_PATH")
|
|
31
|
+
if project_env and os.path.exists(project_env):
|
|
32
|
+
load_dotenv(project_env, override=True)
|
|
33
|
+
else:
|
|
34
|
+
# Fallback for local dev: look in current folder
|
|
35
|
+
load_dotenv(BASE_DIR / ".env", override=True)
|
|
36
|
+
|
|
37
|
+
# 3. Project Identity
|
|
38
|
+
# Must be set in .env or by Orchestrator. Fallback to folder name.
|
|
39
|
+
PROJECT_NAME = os.environ.get("PROJECT_NAME", BASE_DIR.name)
|
|
40
|
+
|
|
41
|
+
# ═══════════════════════════════════════════
|
|
42
|
+
# Core Django Settings (MUST be defined early)
|
|
43
|
+
# ═══════════════════════════════════════════
|
|
44
|
+
ROOT_URLCONF = "{{ project_name }}.core.urls"
|
|
45
|
+
WSGI_APPLICATION = "{{ project_name }}.core.wsgi.application"
|
|
46
|
+
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
|
47
|
+
|
|
48
|
+
# ═══════════════════════════════════════════
|
|
49
|
+
# Import Modules
|
|
50
|
+
# ═══════════════════════════════════════════
|
|
51
|
+
|
|
52
|
+
from .modules.security import * # noqa
|
|
53
|
+
from .modules.apps import * # noqa
|
|
54
|
+
from .modules.middleware import * # noqa
|
|
55
|
+
from .modules.database import * # noqa
|
|
56
|
+
from .modules.cache import * # noqa
|
|
57
|
+
from .modules.internationalization import * # noqa
|
|
58
|
+
from .modules.static import * # noqa
|
|
59
|
+
from .modules.templates import * # noqa
|
|
60
|
+
from .modules.logging import * # noqa
|
|
61
|
+
from .modules.admin import * # noqa
|
|
62
|
+
from .modules.sitemap import * # noqa
|
|
63
|
+
from .modules.codex import * # noqa
|
|
64
|
+
|
|
65
|
+
# ═══════════════════════════════════════════
|
|
66
|
+
# General Settings
|
|
67
|
+
# ═══════════════════════════════════════════
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""
|
|
2
|
+
{{ project_name }} — Development Settings.
|
|
3
|
+
|
|
4
|
+
Inherits from base.py. SQLite, DEBUG=True, verbose logging.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .base import * # noqa: F403
|
|
8
|
+
|
|
9
|
+
# ═══════════════════════════════════════════
|
|
10
|
+
# Debug
|
|
11
|
+
# ═══════════════════════════════════════════
|
|
12
|
+
|
|
13
|
+
DEBUG = True
|
|
14
|
+
|
|
15
|
+
# ═══════════════════════════════════════════
|
|
16
|
+
# Cache — LocMemCache (no Redis needed in dev)
|
|
17
|
+
# ═══════════════════════════════════════════
|
|
18
|
+
|
|
19
|
+
CACHES = {
|
|
20
|
+
"default": {
|
|
21
|
+
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
SESSION_ENGINE = "django.contrib.sessions.backends.db"
|
|
25
|
+
|
|
26
|
+
# ═══════════════════════════════════════════
|
|
27
|
+
# CSRF Trusted Origins
|
|
28
|
+
# ═══════════════════════════════════════════
|
|
29
|
+
|
|
30
|
+
CSRF_TRUSTED_ORIGINS = ["http://localhost:8080"]
|
|
31
|
+
|
|
32
|
+
# ═══════════════════════════════════════════
|
|
33
|
+
# Database — SQLite
|
|
34
|
+
# ═══════════════════════════════════════════
|
|
35
|
+
|
|
36
|
+
# SQLite is already configured in base.py as default.
|
|
37
|
+
# No changes needed here unless you want to override.
|
|
38
|
+
|
|
39
|
+
# ═══════════════════════════════════════════
|
|
40
|
+
# Logging
|
|
41
|
+
# ═══════════════════════════════════════════
|
|
42
|
+
|
|
43
|
+
# In dev, we might want more verbose logging to console
|
|
44
|
+
LOGGING = {
|
|
45
|
+
"version": 1,
|
|
46
|
+
"disable_existing_loggers": False,
|
|
47
|
+
"handlers": {
|
|
48
|
+
"console": {
|
|
49
|
+
"class": "logging.StreamHandler",
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
"root": {
|
|
53
|
+
"handlers": ["console"],
|
|
54
|
+
"level": "DEBUG",
|
|
55
|
+
},
|
|
56
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Settings modules package
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
# Root of Django project: src/backend_django
|
|
5
|
+
BASE_DIR = Path(__file__).resolve().parent.parent.parent.parent
|
|
6
|
+
PROJECT_NAME = os.environ.get("PROJECT_NAME", BASE_DIR.name)
|
|
7
|
+
|
|
8
|
+
UNFOLD = {
|
|
9
|
+
"SITE_TITLE": os.environ.get("ADMIN_SITE_TITLE", f"{PROJECT_NAME.replace('_', ' ').title()} Admin"),
|
|
10
|
+
"SITE_HEADER": os.environ.get("ADMIN_SITE_HEADER", PROJECT_NAME.replace("_", " ").title()),
|
|
11
|
+
"SITE_SYMBOL": "dashboard",
|
|
12
|
+
"COLORS": {
|
|
13
|
+
"primary": {
|
|
14
|
+
"50": "239, 246, 255",
|
|
15
|
+
"100": "219, 234, 254",
|
|
16
|
+
"200": "191, 219, 254",
|
|
17
|
+
"300": "147, 197, 253",
|
|
18
|
+
"400": "96, 165, 250",
|
|
19
|
+
"500": "59, 130, 246",
|
|
20
|
+
"600": "37, 99, 235",
|
|
21
|
+
"700": "29, 78, 216",
|
|
22
|
+
"800": "30, 64, 175",
|
|
23
|
+
"900": "30, 58, 138",
|
|
24
|
+
"950": "23, 37, 84",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
"SIDEBAR": {
|
|
28
|
+
"show_search": True,
|
|
29
|
+
"show_all_applications": False,
|
|
30
|
+
"navigation": [
|
|
31
|
+
{
|
|
32
|
+
"title": "Leads & Contacts",
|
|
33
|
+
"items": [
|
|
34
|
+
{
|
|
35
|
+
"title": "Contact Requests",
|
|
36
|
+
"icon": "mail",
|
|
37
|
+
"link": "/admin/main/contactrequest/",
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"title": "System & Settings",
|
|
43
|
+
"items": [
|
|
44
|
+
{
|
|
45
|
+
"title": "Site Settings",
|
|
46
|
+
"icon": "settings",
|
|
47
|
+
"link": "/admin/system/sitesettings/",
|
|
48
|
+
"permission": lambda request: request.user.is_superuser,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"title": "Static Translations",
|
|
52
|
+
"icon": "translate",
|
|
53
|
+
"link": "/admin/system/statictranslation/",
|
|
54
|
+
"permission": lambda request: request.user.is_superuser,
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"title": "SEO Pages",
|
|
58
|
+
"icon": "search",
|
|
59
|
+
"link": "/admin/system/staticpageseo/",
|
|
60
|
+
"permission": lambda request: request.user.is_superuser,
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"title": "Users",
|
|
64
|
+
"icon": "person",
|
|
65
|
+
"link": "/admin/auth/user/",
|
|
66
|
+
"permission": lambda request: request.user.is_superuser,
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# ═══════════════════════════════════════════
|
|
2
|
+
# Application definition
|
|
3
|
+
# ═══════════════════════════════════════════
|
|
4
|
+
|
|
5
|
+
DJANGO_APPS = [
|
|
6
|
+
"django.contrib.admin",
|
|
7
|
+
"django.contrib.auth",
|
|
8
|
+
"django.contrib.contenttypes",
|
|
9
|
+
"django.contrib.sessions",
|
|
10
|
+
"django.contrib.messages",
|
|
11
|
+
"django.contrib.staticfiles",
|
|
12
|
+
"django.contrib.sitemaps",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
THIRD_PARTY_APPS = [
|
|
16
|
+
# Auth
|
|
17
|
+
"allauth",
|
|
18
|
+
"allauth.account",
|
|
19
|
+
"allauth.socialaccount",
|
|
20
|
+
"allauth.socialaccount.providers.google",
|
|
21
|
+
# Admin
|
|
22
|
+
"unfold",
|
|
23
|
+
"unfold.contrib.filters",
|
|
24
|
+
"unfold.contrib.forms",
|
|
25
|
+
"unfold.contrib.inlines",
|
|
26
|
+
"unfold.contrib.import_export",
|
|
27
|
+
"unfold.contrib.guardian",
|
|
28
|
+
"unfold.contrib.simple_history",
|
|
29
|
+
"django_prometheus",
|
|
30
|
+
"ninja",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
{%- if enable_i18n %}
|
|
34
|
+
THIRD_PARTY_APPS.insert(0, "modeltranslation")
|
|
35
|
+
{%- endif %}
|
|
36
|
+
|
|
37
|
+
# ═══════════════════════════════════════════
|
|
38
|
+
# Codex Library Apps
|
|
39
|
+
# ═══════════════════════════════════════════
|
|
40
|
+
CODEX_APPS = [
|
|
41
|
+
"codex_django.cabinet",
|
|
42
|
+
"codex_django.showcase",
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
# ═══════════════════════════════════════════
|
|
46
|
+
# Codex Library Settings
|
|
47
|
+
# ═══════════════════════════════════════════
|
|
48
|
+
CODEX_SITE_SETTINGS_MODEL = "system.SiteSettings"
|
|
49
|
+
{%- if enable_i18n %}
|
|
50
|
+
CODEX_STATIC_TRANSLATION_MODEL = "system.StaticTranslation"
|
|
51
|
+
{%- endif %}
|
|
52
|
+
CODEX_STATIC_PAGE_SEO_MODEL = "system.StaticPageSeo"
|
|
53
|
+
|
|
54
|
+
LOCAL_APPS = [
|
|
55
|
+
"core",
|
|
56
|
+
"system",
|
|
57
|
+
"cabinet",
|
|
58
|
+
"features.main",
|
|
59
|
+
{%- if with_booking %}
|
|
60
|
+
"booking",
|
|
61
|
+
{%- endif %}
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
INSTALLED_APPS = CODEX_APPS + THIRD_PARTY_APPS + DJANGO_APPS + LOCAL_APPS
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from urllib.parse import quote_plus
|
|
4
|
+
|
|
5
|
+
# In container: /app. Locally: src/backend_django
|
|
6
|
+
BASE_DIR = Path(__file__).resolve().parent.parent.parent.parent
|
|
7
|
+
PROJECT_NAME = BASE_DIR.name
|
|
8
|
+
|
|
9
|
+
# ═══════════════════════════════════════════
|
|
10
|
+
# Redis & ARQ
|
|
11
|
+
# ═══════════════════════════════════════════
|
|
12
|
+
|
|
13
|
+
REDIS_HOST = os.environ.get("REDIS_HOST", "localhost")
|
|
14
|
+
REDIS_PORT = int(os.environ.get("REDIS_PORT", 6379))
|
|
15
|
+
REDIS_PASSWORD = os.environ.get("REDIS_PASSWORD", None)
|
|
16
|
+
|
|
17
|
+
IS_INSIDE_DOCKER = os.path.exists("/.dockerenv")
|
|
18
|
+
if REDIS_HOST == "localhost" and IS_INSIDE_DOCKER:
|
|
19
|
+
REDIS_HOST = "redis"
|
|
20
|
+
|
|
21
|
+
if REDIS_PASSWORD:
|
|
22
|
+
clean_password = REDIS_PASSWORD.strip("'\"").strip()
|
|
23
|
+
encoded_password = quote_plus(clean_password)
|
|
24
|
+
REDIS_URL = f"redis://:{encoded_password}@{REDIS_HOST}:{REDIS_PORT}/0"
|
|
25
|
+
else:
|
|
26
|
+
REDIS_URL = f"redis://{REDIS_HOST}:{REDIS_PORT}/0"
|
|
27
|
+
|
|
28
|
+
# ═══════════════════════════════════════════
|
|
29
|
+
# Cache & Sessions (Isolated by PROJECT_NAME)
|
|
30
|
+
# ═══════════════════════════════════════════
|
|
31
|
+
|
|
32
|
+
CACHES = {
|
|
33
|
+
"default": {
|
|
34
|
+
"BACKEND": "django_redis.cache.RedisCache",
|
|
35
|
+
"LOCATION": REDIS_URL,
|
|
36
|
+
"KEY_PREFIX": PROJECT_NAME,
|
|
37
|
+
"OPTIONS": {
|
|
38
|
+
"CLIENT_CLASS": "django_redis.client.DefaultClient",
|
|
39
|
+
},
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
|
|
44
|
+
SESSION_CACHE_ALIAS = "default"
|
|
45
|
+
SESSION_COOKIE_NAME = f"sessionid_{PROJECT_NAME}"
|
|
46
|
+
|
|
47
|
+
# --- Ratelimit ---
|
|
48
|
+
RATELIMIT_USE_CACHE = "default"
|
|
49
|
+
RATELIMIT_VIEW = "features.main.views.legal.ratelimit_view"
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
# ═══════════════════════════════════════════
|
|
4
|
+
# Authentication & django-allauth
|
|
5
|
+
# ═══════════════════════════════════════════
|
|
6
|
+
|
|
7
|
+
AUTHENTICATION_BACKENDS = [
|
|
8
|
+
"django.contrib.auth.backends.ModelBackend",
|
|
9
|
+
"allauth.account.auth_backends.AuthenticationBackend",
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
ACCOUNT_LOGIN_METHODS = {"email"}
|
|
13
|
+
ACCOUNT_SIGNUP_FIELDS = ["email*", "password1*", "password2*"]
|
|
14
|
+
ACCOUNT_EMAIL_VERIFICATION = "optional"
|
|
15
|
+
ACCOUNT_UNIQUE_EMAIL = True
|
|
16
|
+
|
|
17
|
+
LOGIN_URL = "/cabinet/login/"
|
|
18
|
+
LOGIN_REDIRECT_URL = "/cabinet/"
|
|
19
|
+
LOGOUT_REDIRECT_URL = "/cabinet/login/"
|
|
20
|
+
|
|
21
|
+
SOCIALACCOUNT_PROVIDERS = {
|
|
22
|
+
"google": {
|
|
23
|
+
"APP": {
|
|
24
|
+
"client_id": os.environ.get("GOOGLE_CLIENT_ID", ""),
|
|
25
|
+
"secret": os.environ.get("GOOGLE_CLIENT_SECRET", ""),
|
|
26
|
+
},
|
|
27
|
+
"SCOPE": ["profile", "email"],
|
|
28
|
+
"AUTH_PARAMS": {"access_type": "online"},
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
# ═══════════════════════════════════════════
|
|
33
|
+
# Client Cabinet [codex-django add client-cabinet]
|
|
34
|
+
# Uncomment after running the scaffold command
|
|
35
|
+
# ═══════════════════════════════════════════
|
|
36
|
+
|
|
37
|
+
# ACCOUNT_ADAPTER = "cabinet.adapters.CabinetAccountAdapter"
|
|
38
|
+
# CABINET_DEFAULT_URL = "/cabinet/"
|
|
39
|
+
# CABINET_CLIENT_URL = "/cabinet/my/"
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
import dj_database_url
|
|
5
|
+
|
|
6
|
+
# Root of Django project: src/backend_django
|
|
7
|
+
BASE_DIR = Path(__file__).resolve().parent.parent.parent.parent
|
|
8
|
+
PROJECT_NAME = BASE_DIR.name
|
|
9
|
+
|
|
10
|
+
# ═══════════════════════════════════════════
|
|
11
|
+
# Database
|
|
12
|
+
# ═══════════════════════════════════════════
|
|
13
|
+
|
|
14
|
+
DATABASE_URL = os.environ.get("DATABASE_URL")
|
|
15
|
+
DEBUG = os.environ.get("DEBUG", "False").lower() in ("true", "1", "t")
|
|
16
|
+
IS_DOCKER = os.environ.get("IS_DOCKER", "False").lower() in ("true", "1", "t")
|
|
17
|
+
|
|
18
|
+
if DATABASE_URL:
|
|
19
|
+
# Production (Neon or other)
|
|
20
|
+
DATABASES = {
|
|
21
|
+
"default": dj_database_url.config(
|
|
22
|
+
default=DATABASE_URL,
|
|
23
|
+
conn_max_age=600,
|
|
24
|
+
conn_health_checks=True,
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
elif IS_DOCKER and DEBUG:
|
|
28
|
+
# Local Postgres in Docker Cluster (infra)
|
|
29
|
+
DATABASES = {
|
|
30
|
+
"default": {
|
|
31
|
+
"ENGINE": "django.db.backends.postgresql",
|
|
32
|
+
"NAME": os.environ.get("POSTGRES_DB", "landing_cluster"),
|
|
33
|
+
"USER": os.environ.get("POSTGRES_USER", "postgres"),
|
|
34
|
+
"PASSWORD": os.environ.get("POSTGRES_PASSWORD", "postgres"),
|
|
35
|
+
"HOST": os.environ.get("POSTGRES_HOST", "db"),
|
|
36
|
+
"PORT": os.environ.get("POSTGRES_PORT", "5432"),
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
else:
|
|
40
|
+
# Fallback to SQLite for local development without Docker
|
|
41
|
+
data_dir = BASE_DIR.parent.parent / "data" / "db"
|
|
42
|
+
data_dir.mkdir(parents=True, exist_ok=True)
|
|
43
|
+
|
|
44
|
+
DATABASES = {
|
|
45
|
+
"default": {
|
|
46
|
+
"ENGINE": "django.db.backends.sqlite3",
|
|
47
|
+
"NAME": str(data_dir / f"{PROJECT_NAME}.sqlite3"),
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
from codex_django.core.i18n.discovery import discover_locale_paths
|
|
5
|
+
|
|
6
|
+
# Root of Django project: src/backend_django
|
|
7
|
+
BASE_DIR = Path(__file__).resolve().parent.parent.parent.parent
|
|
8
|
+
|
|
9
|
+
# ═══════════════════════════════════════════
|
|
10
|
+
# Internationalization
|
|
11
|
+
# ═══════════════════════════════════════════
|
|
12
|
+
|
|
13
|
+
LANGUAGE_CODE = os.environ.get("LANGUAGE_CODE", "{{ languages[0] }}")
|
|
14
|
+
TIME_ZONE = os.environ.get("TIME_ZONE", "UTC")
|
|
15
|
+
USE_I18N = {{ enable_i18n }}
|
|
16
|
+
USE_TZ = True
|
|
17
|
+
|
|
18
|
+
{%- if enable_i18n %}
|
|
19
|
+
LANGUAGES = [
|
|
20
|
+
{%- for lang in languages %}
|
|
21
|
+
{%- if lang == 'en' %}
|
|
22
|
+
("en", "English"),
|
|
23
|
+
{%- elif lang == 'ru' %}
|
|
24
|
+
("ru", "Russian"),
|
|
25
|
+
{%- elif lang == 'de' %}
|
|
26
|
+
("de", "Deutsch"),
|
|
27
|
+
{%- elif lang == 'uk' %}
|
|
28
|
+
("uk", "Ukrainian"),
|
|
29
|
+
{%- else %}
|
|
30
|
+
("{{ lang }}", "{{ lang }}"),
|
|
31
|
+
{%- endif %}
|
|
32
|
+
{%- endfor %}
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
try:
|
|
36
|
+
import modeltranslation # noqa
|
|
37
|
+
MODELTRANSLATION_DEFAULT_LANGUAGE = LANGUAGE_CODE.split("-")[0]
|
|
38
|
+
MODELTRANSLATION_LANGUAGES = ({% for lang in languages %}"{{ lang }}"{% if not loop.last %}, {% endif %}{% endfor %})
|
|
39
|
+
except ImportError:
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
LOCALE_PATHS = discover_locale_paths(BASE_DIR)
|
|
43
|
+
{%- endif %}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
# Root of Django project: src/backend_django
|
|
5
|
+
BASE_DIR = Path(__file__).resolve().parent.parent.parent.parent
|
|
6
|
+
|
|
7
|
+
# ═══════════════════════════════════════════
|
|
8
|
+
# Logging (codex-core compatible)
|
|
9
|
+
# ═══════════════════════════════════════════
|
|
10
|
+
|
|
11
|
+
# Loguru / codex-core compatible fields (used in core/logger.py)
|
|
12
|
+
LOG_LEVEL_CONSOLE = os.environ.get("LOG_LEVEL_CONSOLE", "INFO")
|
|
13
|
+
LOG_LEVEL_FILE = os.environ.get("LOG_LEVEL_FILE", "DEBUG")
|
|
14
|
+
LOG_ROTATION = os.environ.get("LOG_ROTATION", "10 MB")
|
|
15
|
+
LOG_DIR = os.environ.get("LOG_DIR", str(BASE_DIR.parent.parent / "logs"))
|
|
16
|
+
|
|
17
|
+
# Standard Django LOGGING (fallback if loguru is disabled/missing)
|
|
18
|
+
LOGGING = {
|
|
19
|
+
"version": 1,
|
|
20
|
+
"disable_existing_loggers": False,
|
|
21
|
+
"formatters": {
|
|
22
|
+
"verbose": {
|
|
23
|
+
"format": "{levelname} {asctime} {module} {process:d} {thread:d} {message}",
|
|
24
|
+
"style": "{",
|
|
25
|
+
},
|
|
26
|
+
"simple": {
|
|
27
|
+
"format": "{levelname} {message}",
|
|
28
|
+
"style": "{",
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
"handlers": {
|
|
32
|
+
"console": {
|
|
33
|
+
"level": LOG_LEVEL_CONSOLE,
|
|
34
|
+
"class": "logging.StreamHandler",
|
|
35
|
+
"formatter": "simple",
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
"loggers": {
|
|
39
|
+
"django": {
|
|
40
|
+
"handlers": ["console"],
|
|
41
|
+
"level": "INFO",
|
|
42
|
+
"propagate": True,
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# ═══════════════════════════════════════════
|
|
2
|
+
# Middleware definition
|
|
3
|
+
# ═══════════════════════════════════════════
|
|
4
|
+
|
|
5
|
+
MIDDLEWARE = [
|
|
6
|
+
"django_prometheus.middleware.PrometheusBeforeMiddleware",
|
|
7
|
+
"django.middleware.security.SecurityMiddleware",
|
|
8
|
+
"django.contrib.sessions.middleware.SessionMiddleware",
|
|
9
|
+
"django.middleware.locale.LocaleMiddleware",
|
|
10
|
+
"django.middleware.common.CommonMiddleware",
|
|
11
|
+
"django.middleware.csrf.CsrfViewMiddleware",
|
|
12
|
+
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
|
13
|
+
"django.contrib.messages.middleware.MessageMiddleware",
|
|
14
|
+
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
|
15
|
+
"django_prometheus.middleware.PrometheusAfterMiddleware",
|
|
16
|
+
"allauth.account.middleware.AccountMiddleware",
|
|
17
|
+
]
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from urllib.parse import urlparse
|
|
3
|
+
|
|
4
|
+
# ═══════════════════════════════════════════
|
|
5
|
+
# Security
|
|
6
|
+
# ═══════════════════════════════════════════
|
|
7
|
+
|
|
8
|
+
SECRET_KEY = os.environ.get("SECRET_KEY", "django-insecure-CHANGE-ME")
|
|
9
|
+
FIELD_ENCRYPTION_KEY = os.environ.get("FIELD_ENCRYPTION_KEY", "")
|
|
10
|
+
|
|
11
|
+
# Main switch for the whole system
|
|
12
|
+
DEBUG = os.environ.get("DEBUG", "True").lower() in ("true", "1", "yes")
|
|
13
|
+
|
|
14
|
+
# --- Smart ALLOWED_HOSTS ---
|
|
15
|
+
ALLOWED_HOSTS = ["localhost", "127.0.0.1", "backend"]
|
|
16
|
+
|
|
17
|
+
env_hosts = os.environ.get("ALLOWED_HOSTS", "")
|
|
18
|
+
if env_hosts:
|
|
19
|
+
ALLOWED_HOSTS.extend([h.strip() for h in env_hosts.split(",") if h.strip()])
|
|
20
|
+
|
|
21
|
+
SITE_BASE_URL = os.environ.get("SITE_BASE_URL", "http://127.0.0.1:8000/")
|
|
22
|
+
if not SITE_BASE_URL.endswith("/"):
|
|
23
|
+
SITE_BASE_URL += "/"
|
|
24
|
+
|
|
25
|
+
# CSRF: include the configured site URL + common local dev ports
|
|
26
|
+
CSRF_TRUSTED_ORIGINS = [SITE_BASE_URL.rstrip("/")]
|
|
27
|
+
if DEBUG:
|
|
28
|
+
CSRF_TRUSTED_ORIGINS += [
|
|
29
|
+
"http://127.0.0.1:8000",
|
|
30
|
+
"http://localhost:8000",
|
|
31
|
+
"http://127.0.0.1:8080",
|
|
32
|
+
"http://localhost:8080",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
# Canonical domain for SEO (no trailing slash)
|
|
36
|
+
CANONICAL_DOMAIN = os.environ.get("CANONICAL_DOMAIN", "")
|
|
37
|
+
if CANONICAL_DOMAIN.endswith("/"):
|
|
38
|
+
CANONICAL_DOMAIN = CANONICAL_DOMAIN[:-1]
|
|
39
|
+
|
|
40
|
+
domain = urlparse(SITE_BASE_URL).netloc
|
|
41
|
+
if domain:
|
|
42
|
+
clean_domain = domain.split(":")[0]
|
|
43
|
+
if clean_domain not in ALLOWED_HOSTS:
|
|
44
|
+
ALLOWED_HOSTS.append(clean_domain)
|
|
45
|
+
|
|
46
|
+
if not clean_domain.startswith("www."):
|
|
47
|
+
www_domain = f"www.{clean_domain}"
|
|
48
|
+
if www_domain not in ALLOWED_HOSTS:
|
|
49
|
+
ALLOWED_HOSTS.append(www_domain)
|
|
50
|
+
|
|
51
|
+
if DEBUG:
|
|
52
|
+
# Allow local tunnels dynamically to ease development
|
|
53
|
+
ALLOWED_HOSTS.extend([".ngrok-free.app", ".ngrok-free.dev", ".ngrok.io", ".loca.lt"])
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# ═══════════════════════════════════════════
|
|
2
|
+
# Sitemap Settings
|
|
3
|
+
# ═══════════════════════════════════════════
|
|
4
|
+
|
|
5
|
+
# List of named URLs to include in the static sitemap
|
|
6
|
+
SITEMAP_STATIC_PAGES = [
|
|
7
|
+
"home",
|
|
8
|
+
"contacts",
|
|
9
|
+
"impressum",
|
|
10
|
+
"datenschutz",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
# Default language for x-default in sitemap
|
|
14
|
+
SITEMAP_DEFAULT_LANGUAGE = "de"
|