Django delegates the files handing to the storage backend. By default Django uses the FileSystemStorage to store files on local filesystem. It is possible to customize storage system to use different storage backend such as AWS S3. This article will walk you through how to configure Django to use AWS S3 as storage backend.
Install the following python libraries that are dependencies
pip install boto3 django-storages
Above command install both boto3 and django-storages libraries
Following are essential settings that are need to be added to settings.py module
Add AWS IAM user Access Key and Access Secret Key
AWS_ACCESS_KEY_ID = <API_ACCESS_KEY> AWS_SECRET_ACCESS_KEY = <API_SECRET_ACCESS_KEY>
Setup the DEFAULT_FILE_STORAGE, so that by default all uploads will use AWS S3 storage unless specified
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
Set following two settings for default bucket name region
AWS_STORAGE_BUCKET_NAME = <Bucket Name>
AWS_S3_REGION_NAME = 'eu-west-2'
If you don’t want AWS S3 storage to be default, it is also possible set storage for specific field as follows
from django.db import models
from storages.backends.s3boto3 import S3Boto3Storage
s3storage = S3Boto3Storage()
class Car(models.Model):
...
photo = models.ImageField(storage=s3storage)
Staring from Django 3.1, it is also possible dynamically select the storage backend using callable as follows
from django.db import models
from .storages import MyLocalStorage, MyS3Storage
def select_storage():
return MyS3Storage() if settings.DEBUG else MyLocalStorage()
class MyModel(models.Model):
my_file = models.FileField(storage=select_storage)
Here is the sample view that saves received (uploaded) files and returns back the URL of objects created in S3 Bucket
@require_POST
def fileUpload(request):
user = request.user # request.user is set by auth backend(session or token) on successful authentication
urls = []
for name, fobj in request.FILES.items():
obj = Uploads.objects.create(user=user)
obj.media.save(name, fobj)
urls.append(obj.media.url)
return HttpResponse(
{
"status": "OK",
"files": urls
}
)
Related model
class UserUpload(models.Model):
user = models.ForeignKey(User, related_name="uploads", on_delete=models.PROTECT)
created = models.DateTimeField(auto_now_add=True)
media = models.FileField(null=True)
It is possible to set bucket and location on fly by accessing storage object on FileField or ImageField as follows
# Assume obj is the model instance which contain the media(FileField) field
obj.media.storage.location = 'users/media'
obj.media.storage.bucket_name = <BUCKET NAME>
Where obj is the model instance and media is the FileField through which accessing storage to set the location (that is folder) to store/save uploaded file
Or set the location per field using upload_to keyword argument
media = models.ImageField(upload_to='avatars')
When working with multiple buckets, we can specify the bucket name itself int he model field as follows
# module models.py
from django.db import models
from storages.backends.s3boto import S3BotoStorage
class UserModel(models.Model):
name = models.CharField()
myfile_1 = models.FileField() # uses the default storage
myfile_2 = models.FileField(storage=S3BotoStorage(bucket='bucket_2')) # Override the default bucket
Leave a Reply