Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Storages using s3boto ignoring MEDIA_URL

I am trying to use django-storages with s3boto in my app and trying to serve media and static files from s3.

I have the following settings in my settings file:

AWS_STORAGE_BUCKET_NAME = '<bucket_name>'
AWS_S3_ACCESS_KEY_ID = '<access_key>'
AWS_S3_SECRET_ACCESS_KEY = '<secret>'
AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME

STATICFILES_LOCATION = 'static'
STATICFILES_STORAGE = '<custom_storage_satic>'

MEDIAFILES_LOCATION = 'media'
DEFAULT_FILE_STORAGE = '<custom_storage_media>'

And my custom_storages.py is

from django.conf import settings
from storages.backends.s3boto import S3BotoStorage

class StaticStorage(S3BotoStorage):
    location = settings.STATICFILES_LOCATION

class MediaStorage(S3BotoStorage):
    location = settings.MEDIAFILES_LOCATION

When I create an image in django, instead of getting the relative path to my image starting with

image.url
'/media/image/<rest_of_the_path>.jpg'

I am getting the absolute url, which is something like

image.url
'https://<s3_bucket_name>.s3.amazonaws.com/media/image/original/'

When I use local storage instead of s3boto, it works as expected and gives me the relative path. Am I missing something here?

like image 435
sshirgao Avatar asked Jan 16 '16 21:01

sshirgao


1 Answers

I struck the same issue when attempting to use the Imgix CDN for my S3 media (I suspect we're both using the same tutorial based on your use of the custom_storages.py override).

Here is an abridged version of the S3BotoStorage class in the django-storages framework. This excerpt highlights the important properties and methods for this issue, namely the custom-domain property.

class S3BotoStorage(Storage):
    location = setting('AWS_LOCATION', '')
    custom_domain = setting('AWS_S3_CUSTOM_DOMAIN')

    def url(self, name, headers=None, response_headers=None, expire=None):
        # Preserve the trailing slash after normalizing the path.
        name = self._normalize_name(self._clean_name(name))
        if self.custom_domain:
            return "%s//%s/%s" % (self.url_protocol, self.custom_domain, filepath_to_uri(name))

As you can see in the url method, a URL is generated to override the STATIC_URL and MEDIA_URL Django settings. Currently the domain of the URL is created with the AWS_S3_CUSTOM_DOMAIN setting, which is why you continue to see the static S3 URL for media files.

So first, in your Django settings file, add a setting describing your CDN's domain.

IMGIX_DOMAIN = 'example.imgix.net'

Then, similar to the override of the location property, add an override to the custom_domain property in your MediaStorage class.

class MediaStorage(S3BotoStorage):
    location = settings.MEDIAFILES_LOCATION
    custom_domain = settings.IMGIX_DOMAIN

Now the final URL to your media files should begin with your CDN's domain, followed by the relative path to your file on the S3 bucket.

like image 166
Alex Avatar answered Sep 30 '22 02:09

Alex