From 3ddd762d74506a0432332e4b8f59655c84ae4795 Mon Sep 17 00:00:00 2001 From: poduck Date: Sat, 29 Nov 2025 21:32:29 -0500 Subject: [PATCH] fix: Add missing Django core apps and DigitalOcean Spaces support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add django.contrib.auth, contenttypes, sessions, sites, messages, staticfiles, and admin to INSTALLED_APPS - Add DigitalOcean Spaces (S3-compatible) storage configuration - Add AWS_S3_ENDPOINT_URL setting for custom S3 endpoints 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- smoothschedule/config/settings/base.py | 7 +++++ smoothschedule/config/settings/production.py | 29 ++++++++++++++++---- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/smoothschedule/config/settings/base.py b/smoothschedule/config/settings/base.py index 072aea9..1ecc3d5 100644 --- a/smoothschedule/config/settings/base.py +++ b/smoothschedule/config/settings/base.py @@ -61,6 +61,13 @@ WSGI_APPLICATION = "config.wsgi.application" # APPS # ------------------------------------------------------------------------------ DJANGO_APPS = [ + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.sites", + "django.contrib.messages", + "django.contrib.staticfiles", + "django.contrib.admin", "django.forms", ] THIRD_PARTY_APPS = [ diff --git a/smoothschedule/config/settings/production.py b/smoothschedule/config/settings/production.py index 0e651c2..6df9911 100644 --- a/smoothschedule/config/settings/production.py +++ b/smoothschedule/config/settings/production.py @@ -68,22 +68,35 @@ SECURE_CONTENT_TYPE_NOSNIFF = env.bool( # STATIC & MEDIA # ------------------------ -# AWS S3 storage is optional - only configure if credentials are provided +# S3-compatible storage (AWS S3 or DigitalOcean Spaces) AWS_ACCESS_KEY_ID = env("DJANGO_AWS_ACCESS_KEY_ID", default="") AWS_SECRET_ACCESS_KEY = env("DJANGO_AWS_SECRET_ACCESS_KEY", default="") AWS_STORAGE_BUCKET_NAME = env("DJANGO_AWS_STORAGE_BUCKET_NAME", default="") +# For DigitalOcean Spaces, use endpoint like: https://nyc3.digitaloceanspaces.com +AWS_S3_ENDPOINT_URL = env("DJANGO_AWS_S3_ENDPOINT_URL", default="") +AWS_S3_REGION_NAME = env("DJANGO_AWS_S3_REGION_NAME", default=None) +AWS_S3_CUSTOM_DOMAIN = env("DJANGO_AWS_S3_CUSTOM_DOMAIN", default=None) if AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY and AWS_STORAGE_BUCKET_NAME: - # Use S3 for media storage + # Use S3/Spaces for media storage AWS_QUERYSTRING_AUTH = False _AWS_EXPIRY = 60 * 60 * 24 * 7 AWS_S3_OBJECT_PARAMETERS = { "CacheControl": f"max-age={_AWS_EXPIRY}, s-maxage={_AWS_EXPIRY}, must-revalidate", } AWS_S3_MAX_MEMORY_SIZE = env.int("DJANGO_AWS_S3_MAX_MEMORY_SIZE", default=100_000_000) - AWS_S3_REGION_NAME = env("DJANGO_AWS_S3_REGION_NAME", default=None) - AWS_S3_CUSTOM_DOMAIN = env("DJANGO_AWS_S3_CUSTOM_DOMAIN", default=None) - aws_s3_domain = AWS_S3_CUSTOM_DOMAIN or f"{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com" + + # Determine the domain for URLs + if AWS_S3_CUSTOM_DOMAIN: + aws_s3_domain = AWS_S3_CUSTOM_DOMAIN + elif AWS_S3_ENDPOINT_URL: + # DigitalOcean Spaces: bucket.region.digitaloceanspaces.com + from urllib.parse import urlparse + endpoint_parts = urlparse(AWS_S3_ENDPOINT_URL) + region = endpoint_parts.netloc.split('.')[0] # e.g., 'nyc3' from nyc3.digitaloceanspaces.com + aws_s3_domain = f"{AWS_STORAGE_BUCKET_NAME}.{region}.digitaloceanspaces.com" + else: + aws_s3_domain = f"{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com" STORAGES = { "default": { @@ -94,10 +107,14 @@ if AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY and AWS_STORAGE_BUCKET_NAME: }, }, "staticfiles": { - "BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage", + "BACKEND": "storages.backends.s3.S3Storage", + "OPTIONS": { + "location": "static", + }, }, } MEDIA_URL = f"https://{aws_s3_domain}/media/" + STATIC_URL = f"https://{aws_s3_domain}/static/" else: # Use local filesystem storage STORAGES = {