Exploring django-storages with S3
django-storages allows you to replace the default file-system storage with S3 or other cloud-provider block storage solutions. In this article, we explore this package by setting it up in a new Django project. I assume some familiarity with Django and S3.
First, let's get our project setup and our dependencies installed:
python3 -m virtualenv venv
source venv/bin/activate
pip install django
pip install django-storages[s3]
pip install python-dotenv
django-admin startproject proj .
./manage.py startapp myapp
Next, let's add myapp
to proj/settings.py
:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'myapp', # new
]
Follow along with this testdriven.io article to get your bucket and user setup on AWS. I found though that the following settings are a little quicker and more up-to-date for getting django-storages setup.
Add environment variables to .env
:
AWS_ACCESS_KEY_ID=<access_key>
AWS_SECRET_ACCESS_KEY=<secret_access_key>
AWS_STORAGE_BUCKET_NAME=<bucket_name>
Setup STORAGES
in settings:
import os
from dotenv import load_dotenv
load_dotenv()
...
# django-storages
# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html
STORAGES = {
"default": {
"BACKEND": "storages.backends.s3.S3Storage",
"OPTIONS": {
"access_key": os.environ['AWS_ACCESS_KEY_ID'],
"secret_key": os.environ['AWS_SECRET_ACCESS_KEY'],
"bucket_name": os.environ['AWS_STORAGE_BUCKET_NAME'],
},
},
"staticfiles": {
"BACKEND": "storages.backends.s3.S3Storage",
"OPTIONS": {
"access_key": os.environ['AWS_ACCESS_KEY_ID'],
"secret_key": os.environ['AWS_SECRET_ACCESS_KEY'],
"bucket_name": os.environ['AWS_STORAGE_BUCKET_NAME'],
},
}
}
And here's a simple model we can use for testing
from django.db import models
class MyModel(models.Model):
upload = models.FileField()
Don't forget to make migrations and migrate.
Dump some contents into hello.txt
: echo "hello" > hello.txt
.
Finally, from the shell, we can upload a file to S3:
>>> from django.core.files import File
>>> f = File(open('hello.txt', 'rb'))
>>> from myapp.models import MyModel
>>> m = MyModel(upload=f)
>>> m.upload.save('hello.txt', f)
>>> m.save()
>>> m
<MyModel: MyModel object (1)>
>>> m.upload
<FieldFile: hello.txt>
>>> m.refresh_from_db()
>>> m.upload
<FieldFile: hello.txt>
>>> m.upload.url
'https://<bucket-name>.s3.us-east-2.amazonaws.com/hello.txt?AWSAccessKeyId=...'
>>> m.upload.file
<S3File: hello.txt>
>>> m.upload.file.read()
b'hello\n'
>>> m.upload.file.read()
b''
>>> m.upload.file.seek(0)
0
>>> quit()
I hope that this brief article gave you an idea for how to setup django-storages in your Django project and how to use it.