diff --git a/backend/config/django/base.py b/backend/config/django/base.py index abab1d50..93778883 100644 --- a/backend/config/django/base.py +++ b/backend/config/django/base.py @@ -3,32 +3,32 @@ Base Django settings for thrillwiki project. Common settings shared across all environments. """ -import environ # type: ignore[import] +import environ import sys from pathlib import Path from decouple import config + # Initialize environment variables with better defaults -env = environ.Env( - DEBUG=(bool, False), - SECRET_KEY=(str, "django-insecure-change-this-in-production"), - ALLOWED_HOSTS=(list, ["localhost", "127.0.0.1"]), - DATABASE_URL=( - str, - "postgis://thrillwiki_user:thrillwiki@localhost:5432/thrillwiki_test_db", - ), - CACHE_URL=(str, "locmem://"), - EMAIL_URL=(str, "console://"), - REDIS_URL=(str, "redis://127.0.0.1:6379/1"), - CORS_ALLOW_ALL_ORIGINS=(bool, False), - CORS_ALLOWED_ORIGINS=(list, []), - API_RATE_LIMIT_PER_MINUTE=(int, 60), - API_RATE_LIMIT_PER_HOUR=(int, 1000), - CACHE_MIDDLEWARE_SECONDS=(int, 300), - CACHE_MIDDLEWARE_KEY_PREFIX=(str, "thrillwiki"), - GDAL_LIBRARY_PATH=(str, "/opt/homebrew/lib/libgdal.dylib"), - GEOS_LIBRARY_PATH=(str, "/opt/homebrew/lib/libgeos_c.dylib"), -) + +DEBUG = config('DEBUG', default=True) +SECRET_KEY = config('SECRET_KEY') +ALLOWED_HOSTS = config('ALLOWED_HOSTS') +DATABASE_URL = config('DATABASE_URL') +CACHE_URL = config('CACHE_URL', default="locmem://") +EMAIL_URL = config('EMAIL_URL', default="console://") +REDIS_URL = config('REDIS_URL', default="redis://127.0.0.1:6379/1") +CORS_ALLOW_ALL_ORIGINS = config('CORS_ALLOW_ALL_ORIGINS', default=False, cast=bool) +CORS_ALLOWED_ORIGINS = config('CORS_ALLOWED_ORIGINS', default=[]) +API_RATE_LIMIT_PER_MINUTE = config('API_RATE_LIMIT_PER_MINUTE', default=60) +API_RATE_LIMIT_PER_HOUR = config('API_RATE_LIMIT_PER_HOUR', default=1000) +CACHE_MIDDLEWARE_SECONDS = config('CACHE_MIDDLEWARE_SECONDS', default=300) +CACHE_MIDDLEWARE_KEY_PREFIX = config( + 'CACHE_MIDDLEWARE_KEY_PREFIX', default="thrillwiki") +GDAL_LIBRARY_PATH = config( + 'GDAL_LIBRARY_PATH', default="/opt/homebrew/lib/libgdal.dylib") +GEOS_LIBRARY_PATH = config( + 'GEOS_LIBRARY_PATH', default="/opt/homebrew/lib/libgeos_c.dylib") # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent.parent @@ -42,16 +42,14 @@ if apps_dir.exists() and str(apps_dir) not in sys.path: environ.Env.read_env(BASE_DIR / ".env") # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = env("SECRET_KEY") - -# SECURITY WARNING: don't run with debug turned on in production! -DEBUG = env("DEBUG") +SECRET_KEY = config('SECRET_KEY') # Allowed hosts -ALLOWED_HOSTS = env("ALLOWED_HOSTS") +ALLOWED_HOSTS = config('ALLOWED_HOSTS') # CSRF trusted origins -CSRF_TRUSTED_ORIGINS = env("CSRF_TRUSTED_ORIGINS", default=[]) # type: ignore[arg-type] +CSRF_TRUSTED_ORIGINS = config('CSRF_TRUSTED_ORIGINS', + default=[]) # type: ignore[arg-type] # Application definition DJANGO_APPS = [ @@ -142,14 +140,23 @@ TEMPLATES = [ WSGI_APPLICATION = "thrillwiki.wsgi.application" # Cloudflare Images Settings -STORAGES = {"default": {"BACKEND": "cloudflare_images.storage.CloudflareImagesStorage"}} +STORAGES = { + "default": { + "BACKEND": "cloudflare_images.storage.CloudflareImagesStorage", + }, + "staticfiles": { + "BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage", + "OPTIONS": { + "location": str(BASE_DIR / "staticfiles"), + }, + }, +} CLOUDFLARE_IMAGES_ACCOUNT_ID = config('CLOUDFLARE_IMAGES_ACCOUNT_ID') -CLOUDFLARE_IMAGES_API_KEY = config('CLOUDFLARE_IMAGES_API_KEY') +CLOUDFLARE_IMAGES_API_TOKEN = config('CLOUDFLARE_IMAGES_API_TOKEN') CLOUDFLARE_IMAGES_ACCOUNT_HASH = config('CLOUDFLARE_IMAGES_ACCOUNT_HASH') CLOUDFLARE_IMAGES_DOMAIN = config( 'CLOUDFLARE_IMAGES_DOMAIN', default='imagedelivery.net') -CLOUDFLARE_EMAIL = config('CLOUDFLARE_EMAIL') # Password validation AUTH_PASSWORD_VALIDATORS = [ { @@ -242,7 +249,7 @@ TEST_RUNNER = "django.test.runner.DiscoverRunner" ROADTRIP_CACHE_TIMEOUT = 3600 * 24 # 24 hours for geocoding ROADTRIP_ROUTE_CACHE_TIMEOUT = 3600 * 6 # 6 hours for routes ROADTRIP_MAX_REQUESTS_PER_SECOND = 1 # Respect OSM rate limits -ROADTRIP_USER_AGENT = "ThrillWiki Road Trip Planner (https://thrillwiki.com)" +ROADTRIP_USER_AGENT = config('ROADTRIP_USER_AGENT') ROADTRIP_REQUEST_TIMEOUT = 10 # seconds ROADTRIP_MAX_RETRIES = 3 ROADTRIP_BACKOFF_FACTOR = 2 @@ -282,18 +289,17 @@ REST_FRAMEWORK = { } # CORS Settings for API -CORS_ALLOWED_ORIGINS = env("CORS_ALLOWED_ORIGINS", default=[]) # type: ignore[arg-type] +CORS_ALLOWED_ORIGINS = config('CORS_ALLOWED_ORIGINS', + default=[]) # type: ignore[arg-type] CORS_ALLOW_CREDENTIALS = True -CORS_ALLOW_ALL_ORIGINS = env("CORS_ALLOW_ALL_ORIGINS", - default=False) # type: ignore[arg-type] +CORS_ALLOW_ALL_ORIGINS = config( + 'CORS_ALLOW_ALL_ORIGINS', default=False, cast=bool) # type: ignore[arg-type] -# API-specific settings -API_RATE_LIMIT_PER_MINUTE = env.int( - "API_RATE_LIMIT_PER_MINUTE", default=60) # type: ignore[arg-type] -API_RATE_LIMIT_PER_HOUR = env.int( - "API_RATE_LIMIT_PER_HOUR", default=1000) # type: ignore[arg-type] -# drf-spectacular settings +API_RATE_LIMIT_PER_MINUTE = config( + 'API_RATE_LIMIT_PER_MINUTE', default=60, cast=int) # type: ignore[arg-type] +API_RATE_LIMIT_PER_HOUR = config( + 'API_RATE_LIMIT_PER_HOUR', default=1000, cast=int) # type: ignore[arg-type] SPECTACULAR_SETTINGS = { "TITLE": "ThrillWiki API", "DESCRIPTION": "Comprehensive theme park and ride information API", @@ -367,11 +373,9 @@ DJANGO_REDIS_CLIENT_CLASS = "django_redis.client.DefaultClient" CACHES = { "default": { "BACKEND": DJANGO_REDIS_CACHE_BACKEND, - # type: ignore[arg-type] - # pyright: ignore[reportArgumentType] # pyright: ignore[reportArgumentType] # type: ignore - "LOCATION": env("REDIS_URL", default="redis://127.0.0.1:6379/1"), + "LOCATION": config('REDIS_URL', default="redis://127.0.0.1:6379/1"), "OPTIONS": { "CLIENT_CLASS": DJANGO_REDIS_CLIENT_CLASS, "PARSER_CLASS": "redis.connection.HiredisParser", @@ -388,17 +392,14 @@ CACHES = { }, "sessions": { "BACKEND": DJANGO_REDIS_CACHE_BACKEND, - # type: ignore[arg-type] - # type: ignore - "LOCATION": env("REDIS_URL", default="redis://127.0.0.1:6379/2"), + "LOCATION": config('REDIS_URL', default="redis://127.0.0.1:6379/2"), "OPTIONS": { "CLIENT_CLASS": DJANGO_REDIS_CLIENT_CLASS, }, }, "api": { "BACKEND": DJANGO_REDIS_CACHE_BACKEND, - # type: ignore[arg-type] - "LOCATION": env("REDIS_URL", default="redis://127.0.0.1:6379/3"), + "LOCATION": config('REDIS_URL', default="redis://127.0.0.1:6379/3"), "OPTIONS": { "CLIENT_CLASS": DJANGO_REDIS_CLIENT_CLASS, }, diff --git a/backend/config/django/local.py b/backend/config/django/local.py index 77a2e086..57182e7c 100644 --- a/backend/config/django/local.py +++ b/backend/config/django/local.py @@ -2,13 +2,9 @@ Local development settings for thrillwiki project. """ -import logging -from .base import * from ..settings import database - -# Import the module and use its members, e.g., email.EMAIL_HOST - -# Import the module and use its members, e.g., security.SECURE_HSTS_SECONDS +import logging +from .base import * # noqa: F403 # Import database configuration DATABASES = database.DATABASES diff --git a/backend/manage.py b/backend/manage.py index 0c76f603..46579896 100755 --- a/backend/manage.py +++ b/backend/manage.py @@ -3,13 +3,14 @@ import os import sys +from decouple import config def main(): """Run administrative tasks.""" # Auto-detect environment based on command line arguments and environment variables settings_module = detect_settings_module() - os.environ.setdefault("DJANGO_SETTINGS_MODULE", settings_module) + config('DJANGO_SETTINGS_MODULE', settings_module) try: from django.core.management import execute_from_command_line