Search code examples
djangodjango-rest-frameworkdjango-storage

Django Rest Framework serialized image returns absolute system url, and not amazon s3 url


I'm currently using django-storages with my application for hosting static and media files. I'm also using imagekit on image uploads to create multiple versions of an image needed across the application.

The problem arises when trying to serialize the images urls. DRF returns a url such as http://127.0.0.1:8000/media/CACHE/images/categories/tilbeh%C3%B8r/tilbehor/2fbf015bd21dba581f5d306ed4248b47.jpg, and when opening this, its returns a completely blank page. What i really need is for it to return the "real" storage url, e.g. https://domain.s3.amazonaws.com/static/media/CACHE/images/categories/tilbeh%C3%B8r/tilbehor/2fbf015bd21dba581f5d306ed4248b47.jpg.

S3 settings:

# aws settings
AWS_ACCESS_KEY_ID = 'secret'
AWS_SECRET_ACCESS_KEY = 'secret'
AWS_STORAGE_BUCKET_NAME = 'domain'
AWS_DEFAULT_ACL = 'public-read'
AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME
AWS_S3_OBJECT_PARAMETERS = {'CacheControl': 'max-age=86400'}
AWS_LOCATION = 'static'

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
    # os.path.join(BASE_DIR, 'frontend/dist'),
]

STATIC_URL = 'https://%s/%s/' % (AWS_S3_CUSTOM_DOMAIN, AWS_LOCATION)
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
MEDIA_ROOT = 'static/media'
MEDIA_URL = '/media/'

models.py

class Category(models.Model):

    def upload_content_file_name(instance, filename):
        """
        Return the location of which to upload the file
        """
       
        return os.path.join('categories/%s/' % instance.name.lower(), filename)
    
    name = models.CharField(
        _('category name'), 
        max_length=255, 
        unique=False
    )
    ...
    image = models.ImageField(
        _('image'),
        upload_to=upload_content_file_name,
        help_text=_(
            'Category image, should only be used on top level parents!'
        ),
        blank=True, 
        null=True,

    )
    image_default = ImageSpecField(source='image', processors=[ResizeToFill(375, 375)], format='JPEG', options={'quality': 90})
    image_sm = ImageSpecField(source='image', processors=[ResizeToFill(640, 300)], format='JPEG', options={'quality': 90})
    image_md = ImageSpecField(source='image', processors=[ResizeToFill(768, 366)], format='JPEG', options={'quality': 90})
    image_lg = ImageSpecField(source='image', processors=[ResizeToFill(1024, 480)], format='JPEG', options={'quality': 90})
    image_xl = ImageSpecField(source='image', processors=[ResizeToFill(1280, 600)], format='JPEG', options={'quality': 90})
    ...

serializers.py

class CategorySerializer(serializers.ModelSerializer):

    image_default = serializers.ImageField(read_only=True)
    image_sm = serializers.ImageField(read_only=True)
    image_md = serializers.ImageField(read_only=True)
    image_lg = serializers.ImageField(read_only=True)
    image_xl = serializers.ImageField(read_only=True)

    class Meta:
        model = Category
        fields = (
            ...
            'image',
            'image_default',
            'image_sm',
            'image_md',
            'image_lg',
            'image_xl',
        )

Solution

  • Uploaded files are not static files but media files, notice that your settings for media files are off

    MEDIA_ROOT = 'static/media'
    MEDIA_URL = '/media/'
    

    when you compare them with static ones

    STATIC_URL = 'https://%s/%s/' % (AWS_S3_CUSTOM_DOMAIN, AWS_LOCATION)
    STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'