[Django]-Upload image files with specific directory structure to amazon s3 django

0👍

Take a look at Django’s File Storage API especially the S3 Storage.

I wouldn’t pass a function as a upload_to keyword. You could consider creating inheriting ImageField and write your own naming method.

0👍

What you can try.. Jump to point 5 for specific folder aiming during upload.

1. Make sure you have the right S3 Permissions and Policy in place. Access ‘Policy’ via permissions tab in AWS S3 console for your specific bucket.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Statement1",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::<your_bucket_name>/*"
        },
        {
            "Sid": "Statement2",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::<your_bucket_name>/images/"
        }
    ]
}

2. Install WhiteNoiseMiddleware & django-storages in your project environment.

pip install whitenoise
pip install django-storages

3. Add the following to MIDDLEWARE= in settings.py

'whitenoise.middleware.WhiteNoiseMiddleware',

4. Following additions in settings.py are required to handle URLs from S3 correctly. The handling is done by django middleware & django-storages automatically

STATICFILES_LOCATION = 'static'
MEDIAFILES_LOCATION = 'media'

AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % os.environ['BUCKET_NAME']
AWS_ACCESS_KEY_ID = os.environ['AWS_KEY']
AWS_SECRET_ACCESS_KEY = os.environ['AWS_ACC_KEY']
AWS_STORAGE_BUCKET_NAME = os.environ['BUCKET_NAME']
AWS_S3_FILE_OVERWRITE = False
AWS_DEFAULT_ACL = None
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3StaticStorage'

MEDIA_ROOT = os.path.join (BASE_DIR, 'static/images/')
STATIC_ROOT = os.path.join (BASE_DIR, 'static')

STATIC_URL = "https://%s/%s/" % (AWS_S3_CUSTOM_DOMAIN, STATICFILES_LOCATION)
MEDIA_URL = "https://%s/%s/" % (AWS_S3_CUSTOM_DOMAIN, MEDIAFILES_LOCATION)

5. For aiming uploads into a precise S3 Bucket folder. (Additional)

In setting.py set media root:

MEDIA_ROOT = os.path.join (BASE_DIR, 'static/images/')

In models.py use ImageFiled and add upload_to= takes in a folder name and creates it with the first upload!:

image_variable = models.ImageField(null=True, default="{default_filename)", upload_to='uploads/') 

Reference: django-storages , whiteNoiseMiddelware, S3 Access Troubleshooting

👤zora

Leave a comment