mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-24 04:11:08 -05:00
- Introduced a comprehensive Secret Management Guide detailing best practices, secret classification, development setup, production management, rotation procedures, and emergency protocols. - Implemented a client-side performance monitoring script to track various metrics including page load performance, paint metrics, layout shifts, and memory usage. - Enhanced search accessibility with keyboard navigation support for search results, ensuring compliance with WCAG standards and improving user experience.
281 lines
11 KiB
Python
281 lines
11 KiB
Python
"""
|
|
Base Django settings for thrillwiki project.
|
|
|
|
This file contains only core Django settings that are common across all
|
|
environments. Environment-specific settings are in local.py, production.py,
|
|
and test.py. Modular configuration is imported from config/settings/.
|
|
|
|
Structure:
|
|
- Core settings (SECRET_KEY, DEBUG, ALLOWED_HOSTS)
|
|
- Application definition (INSTALLED_APPS, MIDDLEWARE)
|
|
- URL and template configuration
|
|
- Internationalization
|
|
- Imports from modular settings (database, cache, security, etc.)
|
|
"""
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
from decouple import config
|
|
|
|
# =============================================================================
|
|
# Path Configuration
|
|
# =============================================================================
|
|
|
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
|
BASE_DIR = Path(__file__).resolve().parent.parent.parent
|
|
|
|
# Add apps directory to sys.path so Django can find the apps
|
|
apps_dir = BASE_DIR / "apps"
|
|
if apps_dir.exists() and str(apps_dir) not in sys.path:
|
|
sys.path.insert(0, str(apps_dir))
|
|
|
|
# =============================================================================
|
|
# Core Settings
|
|
# =============================================================================
|
|
|
|
# SECURITY WARNING: keep the secret key used in production secret!
|
|
SECRET_KEY = config("SECRET_KEY")
|
|
|
|
# SECURITY WARNING: don't run with debug turned on in production!
|
|
DEBUG = config("DEBUG", default=True, cast=bool)
|
|
|
|
# Allowed hosts (comma-separated in .env)
|
|
ALLOWED_HOSTS = config(
|
|
"ALLOWED_HOSTS",
|
|
default="localhost,127.0.0.1",
|
|
cast=lambda v: [s.strip() for s in v.split(",") if s.strip()]
|
|
)
|
|
|
|
# CSRF trusted origins (comma-separated in .env)
|
|
CSRF_TRUSTED_ORIGINS = config(
|
|
"CSRF_TRUSTED_ORIGINS",
|
|
default="",
|
|
cast=lambda v: [s.strip() for s in v.split(",") if s.strip()]
|
|
)
|
|
|
|
# =============================================================================
|
|
# Application Definition
|
|
# =============================================================================
|
|
|
|
DJANGO_APPS = [
|
|
"django.contrib.admin",
|
|
"django.contrib.auth",
|
|
"django.contrib.contenttypes",
|
|
"django.contrib.sessions",
|
|
"django.contrib.messages",
|
|
"django.contrib.staticfiles",
|
|
"django.contrib.sites",
|
|
"django.contrib.gis", # GeoDjango
|
|
]
|
|
|
|
THIRD_PARTY_APPS = [
|
|
# Django Cloudflare Images Toolkit - moved to top to avoid circular imports
|
|
"django_cloudflareimages_toolkit",
|
|
"rest_framework", # Django REST Framework
|
|
# Token authentication (kept for backward compatibility)
|
|
"rest_framework.authtoken",
|
|
"rest_framework_simplejwt", # JWT authentication
|
|
"rest_framework_simplejwt.token_blacklist", # JWT token blacklist
|
|
"dj_rest_auth", # REST authentication with JWT support
|
|
"dj_rest_auth.registration", # REST registration support
|
|
"drf_spectacular", # OpenAPI 3.0 documentation
|
|
"corsheaders", # CORS headers for API
|
|
"pghistory", # django-pghistory
|
|
"pgtrigger", # Required by django-pghistory
|
|
"django_fsm_log", # FSM transition logging
|
|
"allauth",
|
|
"allauth.account",
|
|
"allauth.socialaccount",
|
|
"allauth.socialaccount.providers.google",
|
|
"allauth.socialaccount.providers.discord",
|
|
"django_cleanup",
|
|
"django_filters",
|
|
"django_htmx",
|
|
"whitenoise",
|
|
"django_tailwind_cli",
|
|
"autocomplete", # Django HTMX Autocomplete
|
|
"health_check", # Health checks
|
|
"health_check.db",
|
|
"health_check.cache",
|
|
"health_check.storage",
|
|
"health_check.contrib.migrations",
|
|
"health_check.contrib.redis",
|
|
"django_celery_beat", # Celery beat scheduler
|
|
"django_celery_results", # Celery result backend
|
|
"django_extensions", # Django Extensions for enhanced development tools
|
|
]
|
|
|
|
LOCAL_APPS = [
|
|
"apps.core",
|
|
"apps.accounts",
|
|
"apps.parks",
|
|
"apps.rides",
|
|
"api", # Centralized API app (located at backend/api/)
|
|
"django_forwardemail", # New PyPI package for email service
|
|
"apps.moderation",
|
|
]
|
|
|
|
INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS
|
|
|
|
# =============================================================================
|
|
# Middleware Configuration
|
|
# =============================================================================
|
|
|
|
MIDDLEWARE = [
|
|
"django.middleware.cache.UpdateCacheMiddleware", # Must be first for cache middleware
|
|
"django.middleware.gzip.GZipMiddleware", # Response compression
|
|
"corsheaders.middleware.CorsMiddleware", # CORS middleware for API
|
|
"django.middleware.security.SecurityMiddleware",
|
|
"apps.core.middleware.security_headers.SecurityHeadersMiddleware", # Custom security headers
|
|
"apps.core.middleware.rate_limiting.AuthRateLimitMiddleware", # Rate limiting
|
|
"whitenoise.middleware.WhiteNoiseMiddleware",
|
|
"apps.core.middleware.performance_middleware.PerformanceMiddleware", # Performance monitoring
|
|
"apps.core.middleware.performance_middleware.QueryCountMiddleware", # Database query monitoring
|
|
"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",
|
|
"apps.core.middleware.analytics.PgHistoryContextMiddleware", # History context tracking
|
|
"allauth.account.middleware.AccountMiddleware",
|
|
"django_htmx.middleware.HtmxMiddleware",
|
|
"django.middleware.cache.FetchFromCacheMiddleware", # Must be last for cache middleware
|
|
]
|
|
|
|
# =============================================================================
|
|
# URL Configuration
|
|
# =============================================================================
|
|
|
|
ROOT_URLCONF = "thrillwiki.urls"
|
|
WSGI_APPLICATION = "thrillwiki.wsgi.application"
|
|
|
|
# =============================================================================
|
|
# Template Configuration
|
|
# =============================================================================
|
|
|
|
# Toggle to enable/disable Django template support via env var
|
|
TEMPLATES_ENABLED = config("TEMPLATES_ENABLED", default=True, cast=bool)
|
|
|
|
if TEMPLATES_ENABLED:
|
|
TEMPLATES = [
|
|
{
|
|
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
|
"DIRS": [BASE_DIR / "templates"],
|
|
"APP_DIRS": True,
|
|
"OPTIONS": {
|
|
"context_processors": [
|
|
"django.template.context_processors.debug",
|
|
"django.template.context_processors.request",
|
|
"django.contrib.auth.context_processors.auth",
|
|
"django.contrib.messages.context_processors.messages",
|
|
"apps.moderation.context_processors.moderation_access",
|
|
"apps.core.context_processors.fsm_context",
|
|
"apps.core.context_processors.breadcrumbs",
|
|
"apps.core.context_processors.page_meta",
|
|
]
|
|
},
|
|
}
|
|
]
|
|
else:
|
|
# When templates are disabled, still need APP_DIRS=True for DRF Spectacular
|
|
TEMPLATES = [
|
|
{
|
|
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
|
"APP_DIRS": True,
|
|
"DIRS": [BASE_DIR / "templates/" / "404"],
|
|
"OPTIONS": {
|
|
"context_processors": [
|
|
"django.template.context_processors.debug",
|
|
"django.template.context_processors.request",
|
|
"django.contrib.auth.context_processors.auth",
|
|
"django.contrib.messages.context_processors.messages",
|
|
"apps.moderation.context_processors.moderation_access",
|
|
"apps.core.context_processors.fsm_context",
|
|
"apps.core.context_processors.breadcrumbs",
|
|
"apps.core.context_processors.page_meta",
|
|
]
|
|
},
|
|
}
|
|
]
|
|
|
|
# =============================================================================
|
|
# Custom User Model
|
|
# =============================================================================
|
|
|
|
AUTH_USER_MODEL = "accounts.User"
|
|
|
|
# =============================================================================
|
|
# Internationalization
|
|
# =============================================================================
|
|
|
|
LANGUAGE_CODE = "en-us"
|
|
TIME_ZONE = "America/New_York"
|
|
USE_I18N = True
|
|
USE_TZ = True
|
|
|
|
# =============================================================================
|
|
# Default Primary Key
|
|
# =============================================================================
|
|
|
|
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
|
|
|
# =============================================================================
|
|
# Test Runner
|
|
# =============================================================================
|
|
|
|
TEST_RUNNER = "django.test.runner.DiscoverRunner"
|
|
|
|
# =============================================================================
|
|
# Import Modular Settings
|
|
# =============================================================================
|
|
# Import settings from modular configuration files.
|
|
# These imports add/override settings defined above.
|
|
|
|
# Database configuration (DATABASES, GDAL_LIBRARY_PATH, GEOS_LIBRARY_PATH)
|
|
from config.settings.database import * # noqa: F401,F403,E402
|
|
|
|
# Cache configuration (CACHES, SESSION_*, CACHE_MIDDLEWARE_*)
|
|
from config.settings.cache import * # noqa: F401,F403,E402
|
|
|
|
# Security configuration (SECURE_*, CSRF_*, SESSION_COOKIE_*, AUTH_PASSWORD_VALIDATORS)
|
|
from config.settings.security import * # noqa: F401,F403,E402
|
|
|
|
# Email configuration (EMAIL_*, FORWARD_EMAIL_*)
|
|
from config.settings.email import * # noqa: F401,F403,E402
|
|
|
|
# Logging configuration (LOGGING)
|
|
from config.settings.logging import * # noqa: F401,F403,E402
|
|
|
|
# REST Framework configuration (REST_FRAMEWORK, CORS_*, SIMPLE_JWT, REST_AUTH, SPECTACULAR_SETTINGS)
|
|
from config.settings.rest_framework import * # noqa: F401,F403,E402
|
|
|
|
# Third-party configuration (ACCOUNT_*, SOCIALACCOUNT_*, CLOUDFLARE_IMAGES, etc.)
|
|
from config.settings.third_party import * # noqa: F401,F403,E402
|
|
|
|
# Storage configuration (STATIC_*, MEDIA_*, STORAGES, WHITENOISE_*, FILE_UPLOAD_*)
|
|
from config.settings.storage import * # noqa: F401,F403,E402
|
|
|
|
# =============================================================================
|
|
# Post-Import Overrides
|
|
# =============================================================================
|
|
# Settings that need to reference values from imported modules
|
|
|
|
# Update SimpleJWT to use the SECRET_KEY
|
|
SIMPLE_JWT["SIGNING_KEY"] = SECRET_KEY # noqa: F405
|
|
|
|
# =============================================================================
|
|
# Startup Validation
|
|
# =============================================================================
|
|
# Run configuration validation after all settings are loaded.
|
|
# These validations catch configuration errors early during Django startup.
|
|
|
|
from config.settings.secrets import run_startup_validation as validate_secrets # noqa: E402
|
|
from config.settings.validation import run_startup_validation as validate_config # noqa: E402
|
|
|
|
# Run secret validation (fails fast in production, warns in development)
|
|
validate_secrets()
|
|
|
|
# Run configuration validation (fails fast in production, warns in development)
|
|
validate_config()
|