JChao
JChao

Reputation: 2319

How to make django uploaded images to display in CloudFront frontend + Beanstalk Backend

I have created a backend django app using AWS Beanstalk, and a frontend reactjs app deployed using cloudfront (plus S3)

I have a model in backend that does

class EnhancedUser(AbstractUser):
    # some other attributes
    picture = models.ImageField(blank=True)

my settings.py has

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '<my_elastic_beanstalk_domain>/media/'

Since I'm using cloudfront, if i just set the MEDIA_URL to /media/, it would just append /media/ to my cloudfront url, so I have to hardcode it to my backend url

and then, following the django docs, I added the static part to my urls.py

urlpatterns = [
    path('admin/', admin.site.urls),
    # some other urls
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Note that django doc does mention we can't use absolute url for MEDIA_URL, but I have no alternative solution at the moment

When I upload my image, it doesn't get stored in the right place, but I cannot open it with the url. It returns a 404 saying the img's url is not part of urls list

My question is:

  1. How do I set it up so I can display the image
  2. Since the images will be updated through users/admins, these will be stored in the EC2 instance created in beanstalk, so every time I deploy, I think they will be wiped. How do I prevent this?

Upvotes: 3

Views: 438

Answers (1)

Ben
Ben

Reputation: 2547

Take a look at using django-storages to save your uploads. I use S3 for storing uploads of a django/docker/EB deployment, and include django settings that look something like this (I keep them in settings/deployment.py):

if 'AWS_ACCESS_KEY_ID' in os.environ:
    # Use Amazon S3 for storage for uploaded media files
    # Keep them private by default
    DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
    # Amazon S3 settings.
    AWS_ACCESS_KEY_ID = os.environ["AWS_ACCESS_KEY_ID"]
    AWS_SECRET_ACCESS_KEY = os.environ["AWS_SECRET_ACCESS_KEY"]
    AWS_STORAGE_BUCKET_NAME = os.environ["AWS_STORAGE_BUCKET_NAME"]
    AWS_S3_REGION_NAME = os.environ.get("AWS_S3_REGION_NAME", None)
    AWS_S3_SIGNATURE_VERSION = 's3v4'
    AWS_AUTO_CREATE_BUCKET = False
    AWS_HEADERS = {"Cache-Control": "public, max-age=86400"}
    AWS_S3_FILE_OVERWRITE = False
    AWS_DEFAULT_ACL = 'private'
    AWS_QUERYSTING_AUTH = True
    AWS_QUERYSTRING_EXPIRE = 600
    AWS_S3_SECURE_URLS = True
    AWS_REDUCED_REDUNDANCY = False
    AWS_IS_GZIPPED = False

    MEDIA_ROOT = '/'
    MEDIA_URL = 'https://s3.{}.amazonaws.com/{}/'.format(
        AWS_S3_REGION_NAME, AWS_STORAGE_BUCKET_NAME)
    USING_AWS = True

Upvotes: 3

Related Questions