pythondjangoamazon-s3digital-oceandigital-ocean-spaces

Django Static url not working with {% static %} with Digital Ocean CDN


I have my static files being stored in DigitalOcean CDN. I have multiple spaces 1 for clients and 1 for static assets and I use django-storages.

Here is my config:

AWS_S3_REGION_NAME = 'nyc3'
AWS_S3_ENDPOINT_URL = f'https://{AWS_S3_REGION_NAME}.digitaloceanspaces.com'
AWS_DEFAULT_ACL = 'private'
AWS_DEFAULT_BUCKET = 'exactestate-staging'
AWS_RESOURCE = session.resource('s3',
                            region_name=AWS_S3_REGION_NAME,
                            endpoint_url=AWS_S3_ENDPOINT_URL,
                            aws_access_key_id=AWS_ACCESS_KEY_ID,
                            aws_secret_access_key=AWS_SECRET_ACCESS_KEY)

AWS_CLIENT = boto3.client('s3',
                      region_name=AWS_S3_REGION_NAME,
                      endpoint_url=AWS_S3_ENDPOINT_URL,
                      aws_access_key_id=AWS_ACCESS_KEY_ID,
                      aws_secret_access_key=AWS_SECRET_ACCESS_KEY)
# Django’s STATIC_URL must end in a slash and the AWS_S3_CUSTOM_DOMAIN must not. It is best to set this variable independently of STATIC_URL.
AWS_S3_CUSTOM_DOMAIN = f'{AWS_DEFAULT_BUCKET}.{AWS_S3_REGION_NAME}.digitaloceanspaces.com'
STATIC_URL = f'https://{AWS_DEFAULT_BUCKET}.{AWS_S3_REGION_NAME}.digitaloceanspaces.com/static/'

STATICFILES_STORAGE = 'storage_backends.StaticStorage'

For some reason if I do not have: AWS_S3_CUSTOM_DOMAIN = f'{AWS_DEFAULT_BUCKET}.{AWS_S3_REGION_NAME}.digitaloceanspaces.com' set, my {% static %} tag uses the AWS_S3_ENDPOINT_URL as the value...but I need it to use what I set for AWS_S3_CUSTOM_DOMAIN.

Normally setting AWS_S3_CUSTOM_DOMAIN would be fine but now all file.url calls also go to static instead of my client space...how can I fix this?


Solution

  • Okay so I figured out a bit and solved my problem by altering my StaticStorage class to build the proper URLs I needed.

    from abc import ABC
    
    from django.conf import settings
    from storages.backends.s3boto3 import S3Boto3Storage
    
    
    class StaticStorage(S3Boto3Storage, ABC):
        def __init__(self, *args, **kwargs):
            super().__init__( *args, **kwargs)
    
            if hasattr(settings, 'STAGING') and settings.STAGING is True:
                # will have different static area
                self.bucket_name = 'exactestate-stg'
                self.region_name = 'sfo2'
                self.endpoint = f'https://{self.region_name}.digitaloceanspaces.com'
                # for building static is already in name
                # no cdn for staging
                self.static_url = f'https://{self.bucket_name}.{self.region_name}.digitaloceanspaces.com/'
    
            else:
                self.bucket_name = 'exactestate-prod'
                self.region_name = 'sfo2'
                self.endpoint = f'https://{self.region_name}.digitaloceanspaces.com'
                self.static_url = f'https://{self.bucket_name}.{self.region_name}.cdn.digitaloceanspaces.com/'
    
        location = 'static'
        default_acl = 'public-read'
    
        # fix to fix the url for staging and prod to have the right url for {% static ... %]
        def url(self, name, parameters=None, expire=None, http_method=None):
            # Preserve the trailing slash after normalizing the path.
            name = self._normalize_name(self._clean_name(name))
    
            params = parameters.copy() if parameters else {}
            params['Bucket'] = self.bucket.name
            params['Key'] = name
            url = self.bucket.meta.client.generate_presigned_url('get_object', Params=params,
                                                                 ExpiresIn=expire, HttpMethod=http_method)
            # if self.querystring_auth:
            #     return url
    
            val_to_return = self._strip_signing_parameters(url)
            new_val = f'{self.static_url}{name}'        # this works
            return new_val
    
    
    

    Basically my issue was that altering AWS_S3_CUSTOM_DOMAIN altered the domain used for my files in a way that I could no longer build my correct URL as it overrode the endpoint url. To fix this I simply took the url() method from S3Boto3Storage and ensured my URL was accurate for my CDN.