import logging import os import sys from pathlib import Path from typing import Any from dotenv import load_dotenv from config.settings_utils import get_data_dir logger: logging.Logger = logging.getLogger("tussilago.settings") load_dotenv() DEBUG: bool = os.getenv("DJANGO_DEBUG", "False").lower() == "true" TESTING: bool = "test" in sys.argv or "PYTEST_VERSION" in os.environ BASE_DIR: Path = Path(__file__).resolve().parent.parent DATA_DIR: Path = get_data_dir() DATA_DIR.mkdir(exist_ok=True) DB_DIR: Path = DATA_DIR / "db" DB_DIR.mkdir(exist_ok=True) SECRET_KEY: str = os.getenv("DJANGO_SECRET_KEY", default="") if not SECRET_KEY: logger.error("DJANGO_SECRET_KEY environment variable is not set.") sys.exit(1) # Exit with a non-zero status code to indicate an error TIME_ZONE: str = "UTC" USE_I18N: bool = False USE_THOUSAND_SEPARATOR: bool = True DATE_FORMAT = "j F Y" # 31 January 2006 TIME_FORMAT = "H:i" # 15:04 DATETIME_FORMAT = "j F Y H:i" # 31 January 2006 15:04 YEAR_MONTH_FORMAT = "F Y" # January 2006 MONTH_DAY_FORMAT = "j F" # 31 January SHORT_DATE_FORMAT = "Y-m-d" # 2006-10-25 SHORT_DATETIME_FORMAT = "Y-m-d H:i" # 2006-10-25 15:04 FIRST_DAY_OF_WEEK = 1 # Monday DATE_INPUT_FORMATS: list[str] = [ "%Y-%m-%d", # 2006-10-25 "%m/%d/%Y", # 10/25/2006 "%m/%d/%y", # 10/25/06 ] DECIMAL_SEPARATOR = "," THOUSAND_SEPARATOR = "\xa0" # non-breaking space NUMBER_GROUPING = 3 URLIZE_ASSUME_HTTPS: bool = True USE_TZ: bool = True ROOT_URLCONF: str = "config.urls" ALLOWED_HOSTS: list[str] = [] WSGI_APPLICATION: str = "config.wsgi.application" ADMINS: list[tuple[str, str]] = [("Joakim Hellsén", "tlovinator@gmail.com")] STATIC_ROOT: Path = DATA_DIR / "staticfiles" STATIC_ROOT.mkdir(exist_ok=True) STATIC_URL = "static/" STATICFILES_DIRS: list[Path] = [BASE_DIR / "static"] MEDIA_ROOT: Path = DATA_DIR / "media" MEDIA_ROOT.mkdir(exist_ok=True) MEDIA_URL = "/media/" if DEBUG: INTERNAL_IPS: list[str] = ["127.0.0.1", "localhost"] INSTALLED_APPS: list[str] = [ "config.apps.TussilagoConfig", "control_plane.apps.ControlPlaneConfig", "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", ] MIDDLEWARE: list[str] = [ "django.middleware.security.SecurityMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "django.middleware.common.CommonMiddleware", "django.middleware.csrf.CsrfViewMiddleware", "django.contrib.auth.middleware.AuthenticationMiddleware", "django.contrib.messages.middleware.MessageMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware", ] TEMPLATES: list[dict[str, str | bool | list[str] | dict[str, list[str]]]] = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", "DIRS": [], "APP_DIRS": True, "OPTIONS": { "context_processors": [ "django.template.context_processors.request", "django.contrib.auth.context_processors.auth", "django.contrib.messages.context_processors.messages", ], }, }, ] DATABASES: dict[str, dict[str, str | Path | dict[str, str | int]]] = { "default": { "ENGINE": "django.db.backends.sqlite3", "NAME": DB_DIR / "tussilago.sqlite3", "OPTIONS": { "transaction_mode": "IMMEDIATE", "timeout": 5, # seconds "init_command": """ PRAGMA journal_mode=WAL; PRAGMA synchronous=NORMAL; PRAGMA mmap_size=134217728; PRAGMA journal_size_limit=27103364; PRAGMA cache_size=2000; """, }, }, } DISABLE_SERVER_SIDE_CURSORS: bool = True CELERY_BROKER_URL: str = os.getenv( "TUSSILAGO_CELERY_BROKER_URL", "memory://" if DEBUG or TESTING else "", ) CELERY_RESULT_BACKEND: str = os.getenv( "TUSSILAGO_CELERY_RESULT_BACKEND", "cache+memory://" if DEBUG or TESTING else "", ) CELERY_ACCEPT_CONTENT: list[str] = ["json"] CELERY_TASK_SERIALIZER: str = "json" CELERY_RESULT_SERIALIZER: str = "json" CELERY_TIMEZONE: str = TIME_ZONE CELERY_TASK_ALWAYS_EAGER: bool = TESTING CELERY_TASK_EAGER_PROPAGATES: bool = TESTING CELERY_TASK_DEFAULT_QUEUE: str = "control-plane" AUTH_PASSWORD_VALIDATORS: list[dict[str, str]] = [ { "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", }, { "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", }, { "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", }, { "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", }, ] # Logging configuration LOGGING: dict[str, Any] = { "version": 1, "disable_existing_loggers": False, "handlers": { "console": { "level": "DEBUG", "class": "logging.StreamHandler", }, }, "loggers": { "": { "handlers": ["console"], "level": "INFO", "propagate": True, }, "tussilago": { "handlers": ["console"], "level": "DEBUG", "propagate": False, }, "django": { "handlers": ["console"], "level": "INFO", "propagate": False, }, "django.utils.autoreload": { "handlers": ["console"], "level": "INFO", "propagate": True, }, }, } if DEBUG or TESTING: MIDDLEWARE.extend(( "zeal.middleware.zeal_middleware", "debug_toolbar.middleware.DebugToolbarMiddleware", "django_browser_reload.middleware.BrowserReloadMiddleware", )) INSTALLED_APPS.extend(( "zeal", "debug_toolbar", "django_watchfiles", "django_browser_reload", )) from config.dev_autoreload import install_watchfiles_reloader_patch install_watchfiles_reloader_patch(project_root=BASE_DIR) # Customize the config to support htmx boosting. DEBUG_TOOLBAR_CONFIG: dict[str, str] = {"ROOT_TAG_EXTRA_ATTRS": "hx-preserve"}