Django — Using Azure blob storage to handle static & media assets — from scratch
This post was originally published on Medium.
In this tutorial, we will see how to use the Azure Blob service to handle static assets & media assets (user uploaded files) with Django.
Fundations
I need to create a Resource Group, Storage Account and two containers. I will use the following naming convention:
- Resource group name: DemoDjangoBlob
- Storage Account name: djangoaccountstorage
- Media container name: media
- Static container name: static
Resources creation using Azure CLI
1
2
3
4
5
6
7
8
9
10
# Create resource group named DemoDjangoBlob
$ az group create -l westeurope -n DemoDjangoBlob
# Create storage account named djangoaccountstorage
$ az storage account create -n djangoaccountstorage -g DemoDjangoBlob -l westeurope --sku Standard_LRS --https-only true
# (optional) Update storage account to V2
$ az storage account update -n djangoaccountstorage -g DemoDjangoBlob --set kind=StorageV2
# Create the "media" container_
$ az storage container create -n media --account-name djangoaccountstorage --public-access blob
# Create the "static" container
$ az storage container create -n static --account-name djangoaccountstorage --public-access blob
Resources creation using Azure Portal
Select Subscription and display Resource group list. Click on “Create Resource group”.
Click on “Create”, go to the resource group and Click on “Create resources”.
Search “storage account” and Click on “Create”. Configure the Storage Account as following:
Enable “Secure transfer required” in Advanced tab and Create the resource.
Go to the resource on “Blob service” item menu. Create static
and media
containers with “Blob” public access level :
It is done. We will need to manage Storage Account Keys later, they are located in “Access Keys” item menu.
Install and configure Django
The easiest way is to install everything using pipenv
:
1
2
3
4
5
6
7
8
# Basic Django installation_
$ mkdir demo-django-azure_blob
$ cd demo-django-azure_blob/
$ pipenv install django
$ pipenv install django-storages[azure]
$ pipenv shell
(demo-django-azure_blob) $ django-admin.py startproject backend .
(demo-django-azure_blob) $ python manage.py migrate
Add storages
to INSTALLED_APPS
in settings.py module:
1
2
3
4
5
6
7
8
9
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'storages',
]
Then, Add the following lines at the end of settings.py module :
1
2
3
4
5
6
7
8
9
10
DEFAULT_FILE_STORAGE = 'backend.custom_azure.AzureMediaStorage'
STATICFILES_STORAGE = 'backend.custom_azure.AzureStaticStorage'
STATIC_LOCATION = "static"
MEDIA_LOCATION = "media"
AZURE_ACCOUNT_NAME = "djangoaccountstorage"
AZURE_CUSTOM_DOMAIN = f'{AZURE_ACCOUNT_NAME}.blob.core.windows.net'
STATIC_URL = f'https://{AZURE_CUSTOM_DOMAIN}/{STATIC_LOCATION}/'
MEDIA_URL = f'https://{AZURE_CUSTOM_DOMAIN}/{MEDIA_LOCATION}/'
AZURE_ACCOUNT_NAME
must be replaced by the storage account name.
Finally, create a custom_azure.py file in backend/ folder and replace account_name
and account_key
values:
1
2
3
4
5
6
7
8
9
10
11
12
13
from storages.backends.azure_storage import AzureStorage
class AzureMediaStorage(AzureStorage):
account_name = 'djangoaccountstorage' # <storage_account_name>
account_key = 'your_key_here' # <storage_account_key>
azure_container = 'media'
expiration_secs = None
class AzureStaticStorage(AzureStorage):
account_name = 'djangoaccountstorage' # <storage_account_name>
account_key = 'your_key_here' # <storage_account_key>
azure_container = 'static'
expiration_secs = None
Get storage account key with Azure CLI :
1
$ az storage account keys list -n djangoaccountstorage -g DemoDjangoBlob
It is almost finished. Azure resources and Django are ready, let’s migrate static & media files now.
Migrate static files
collectstatic
command will copy files to remote location now.
1
2
3
4
5
6
7
(demo-django-blob) $ python manage.py collectstatic
You have requested to collect static files at the destination
location as specified in your settings.
This will overwrite existing files!
Are you sure you want to do this?
Type 'yes' to continue, or 'no' to cancel: yes
119 static files copied
119 static files were copied but I have an “empty” project. In fact, Django Admin static files (css, fonts, js and img) were copied.
Test it
Run the local server without static files:
1
(demo-django-blob) $ python manage.py runserver --nostatic
Navigate to http://127.0.0.1:8000/admin/login/?next=/admin/
We have the following Django administration page :
Check source code:
Conclusions
Using Azure blob service with Django is pretty easy thanks to django-storages library. Moreover, features like Azure CDN will come soon 😃.
Next steps can be :
- Store
account_name
andaccount_key
inside environment variables. - Deal with Cross-Origin Ressource Sharing supported by Azure Storage Services
Hope this tutorial was helpful. Feel free to leave me a feedback 😏.
PS: This tutorial was largely inspired by the tutorial from Vitor Freitas : How to Setup Amazon S3 in a Django Project.