""" Database configuration for thrillwiki project. This module configures database connections, connection pooling, and GeoDjango settings using python-decouple for consistent environment variable management. Why python-decouple? - Already used in base.py for consistency - Simpler API than django-environ - Sufficient for our configuration needs - Better separation of config from code Database URL Format: - PostgreSQL: postgres://user:password@host:port/dbname - PostGIS: postgis://user:password@host:port/dbname - SQLite: sqlite:///path/to/db.sqlite3 - SpatiaLite: spatialite:///path/to/db.sqlite3 """ from decouple import config import dj_database_url # ============================================================================= # Database Configuration # ============================================================================= # Parse DATABASE_URL environment variable into Django database settings DATABASE_URL = config( "DATABASE_URL", default="postgis://thrillwiki_user:thrillwiki@localhost:5432/thrillwiki_test_db" ) # Parse the database URL db_config = dj_database_url.parse(DATABASE_URL) # Force PostGIS backend for spatial data support # This ensures GeoDjango features work correctly if "postgis" in DATABASE_URL or "postgresql" in DATABASE_URL: db_config["ENGINE"] = "django.contrib.gis.db.backends.postgis" DATABASES = { "default": db_config, } # ============================================================================= # Database Connection Pooling Configuration # ============================================================================= # Connection pooling improves performance by reusing database connections # CONN_MAX_AGE: How long to keep connections open (in seconds) # 0 = Close after each request (default Django behavior) # None = Unlimited reuse (not recommended) # 600 = 10 minutes (good balance for most applications) CONN_MAX_AGE = config("DATABASE_CONN_MAX_AGE", default=600, cast=int) # Apply CONN_MAX_AGE to the default database DATABASES["default"]["CONN_MAX_AGE"] = CONN_MAX_AGE # ============================================================================= # Database Connection Options (PostgreSQL-specific) # ============================================================================= # These settings are passed to psycopg2 when creating new connections DATABASE_OPTIONS = { # Connection timeout in seconds "connect_timeout": config("DATABASE_CONNECT_TIMEOUT", default=10, cast=int), # Query timeout in milliseconds (30 seconds default) # This prevents runaway queries from blocking the database "options": f"-c statement_timeout={config('DATABASE_STATEMENT_TIMEOUT', default=30000, cast=int)}", } # Apply options to PostgreSQL databases if "postgis" in DATABASE_URL or "postgresql" in DATABASE_URL: DATABASES["default"].setdefault("OPTIONS", {}) DATABASES["default"]["OPTIONS"].update(DATABASE_OPTIONS) # ============================================================================= # GeoDjango Settings # ============================================================================= # Library paths for GDAL and GEOS (required for GeoDjango) # These vary by operating system and installation method # macOS with Homebrew (default) # Linux: /usr/lib/x86_64-linux-gnu/libgdal.so # Docker: Usually handled by the image 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" ) # ============================================================================= # Read Replica Configuration (Optional) # ============================================================================= # Configure read replicas for read-heavy workloads # Set DATABASE_READ_REPLICA_URL to enable DATABASE_READ_REPLICA_URL = config("DATABASE_READ_REPLICA_URL", default="") if DATABASE_READ_REPLICA_URL: replica_config = dj_database_url.parse(DATABASE_READ_REPLICA_URL) if "postgis" in DATABASE_READ_REPLICA_URL or "postgresql" in DATABASE_READ_REPLICA_URL: replica_config["ENGINE"] = "django.contrib.gis.db.backends.postgis" replica_config["CONN_MAX_AGE"] = CONN_MAX_AGE DATABASES["replica"] = replica_config