Question

Django Static Files Not Uploading to Digital Ocean Spaces Despite Correct Configuration

I’m having issues with Django’s static files not being uploaded to Digital Ocean Spaces (S3-compatible storage) in production since I’ve upgraded to Django 5.2 from 4.2. As part of this upgrade I also updated python, boto3 and django-storages.

The collectstatic command appears to run successfully locally, but files are not being updated in the Spaces bucket. Additionally, some static files (particularly CSS) are being served as downloads instead of being rendered in the browser.

Current Setup

  • Django 5.2
  • Digital Ocean Spaces (S3-compatible storage)
  • Custom storage backend using django-storages
  • Production environment (DEBUG=False)
  • Here is my Pipfile using pipenv for dependencies
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
django = "==5.2"
pillow = "*"
python-dotenv = "*"
stripe = "*"
mailchimp-marketing = "*"
dotenv = "*"
gunicorn = "*"
psycopg2 = "*"
django-storages = "==1.14.2"
boto3 = "==1.34.69"
weasyprint = "*"

[dev-packages]

[requires]
python_version = "3.12"

Configuration

# settings.py (production settings)
AWS_ACCESS_KEY_ID = os.getenv('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = os.getenv('AWS_SECRET_ACCESS_KEY')
AWS_STORAGE_BUCKET_NAME = 'equine-pro'
AWS_S3_ENDPOINT_URL = 'https://ams3.digitaloceanspaces.com'
AWS_S3_OBJECT_PARAMETERS = {
    'CacheControl': 'max-age=86400',
    'ACL': 'public-read'
}
AWS_DEFAULT_ACL = 'public-read'
AWS_LOCATION = 'static'
AWS_S3_CUSTOM_DOMAIN = 'equine-pro.ams3.cdn.digitaloceanspaces.com'
AWS_S3_REGION_NAME = 'ams3'
AWS_S3_FILE_OVERWRITE = True
AWS_QUERYSTRING_AUTH = False
AWS_S3_VERIFY = True
AWS_S3_SIGNATURE_VERSION = 's3v4'
AWS_S3_ADDRESSING_STYLE = 'virtual'

STATICFILES_STORAGE = 'equineproclinic.storage_backends.StaticStorage'

Custom Storage Backend

# storage_backends.py
from storages.backends.s3boto3 import S3Boto3Storage
import logging

logger = logging.getLogger(__name__)

class StaticStorage(S3Boto3Storage):
    location = 'static'
    default_acl = 'public-read'

    def _save(self, name, content):
        logger.info(f"Attempting to save {name}")
        try:
            # Set content type based on file extension
            content_type = self._get_content_type(name)
            params = {
                'ACL': self.default_acl,
                'CacheControl': 'max-age=86400',
                'ContentType': content_type
            }
            return super()._save(name, content, extra_args=params)
        except Exception as e:
            logger.error(f"Error saving {name}: {str(e)}")
            raise

Additional Context

  • The application is deployed on Digital Ocean App Platform
  • Static files are served through the CDN
  • All AWS credentials are confirmed to be present and correct
  • The storage backend can be initialized successfully (verified through custom management command)

Any help or guidance would be greatly appreciated!

What I’ve Tried

  1. Verified AWS credentials are correctly set in Digital Oceans environment variables
  2. Updated CORS settings in Digital Ocean Spaces to allow GET, PUT, POST, DELETE and HEAD methods
  3. Created a custom management command to verify storage configuration
  4. Added extensive logging to track the upload process
  5. Cleared the static files directory and ran collectstatic with --clear flag

Current Behavior

  1. collectstatic command runs without errors
  2. Files are copied locally but not uploaded to Spaces
  3. No errors are logged during the process
  4. Existing files in Spaces bucket are not updated
  5. Some static files (CSS) are served as downloads instead of being rendered

Submit an answer


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Sign In or Sign Up to Answer

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

alexdo
Site Moderator
Site Moderator badge
May 12, 2025

Heya, @jorienwalraven

You can check if collectstatic is using your custom storage

python manage.py shell 
>>> from django.conf import settings 
>>> >>> settings.STATICFILES_STORAGE

Make sure it returns equineproclinic.storage_backends.StaticStorage. If not, Django isn’t picking up the right backend.

Also, sometimes the hashed filenames make Django think nothing changed:

python manage.py collectstatic --noinput --clear --ignore=*.gz

Add --verbosity 3 to confirm which files are uploaded.

Hope that this helps!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.