IAN WALDRON IAN WALDRON

Support for Pre-Django 4.2 Storage Configuration Removed In Django 5.1

Support for the file/media and static file storage configurations has been removed forcing adoption of the new STORAGES dictionary in settings.py.
August 8, 2024

In Django 5.1 you need to migrate "DEFAULT_FILE_STORAGE" and "STATICFILES_STORAGE" (deprecated Django 4.2) to the "STORAGES" setting.

Background

I'm serving static files for my Django projects running k8s with django-storages and boto3 on Digital Ocean's object storage platform. I noticed on August 7, 2024, following an update to a project that static files were completely down. I couldn't run the "collectstatic" command nor would the production site correctly retrieve static files.

After reviewing the logs, it was clear the problem was on my side since I was receiving a file permissions issue and not a permissions issue on the bucket. However, I hadn't made any configuration changes and I thought my requirements.txt was configured to only include patch (non-breaking) changes whenever a container is built.

I was wrong. My requirements.txt file reflected "Django~=5.0" which will advance the version to "5.1," when available, possibly including breaking changes. That's what happened here. On August 7, 2024, Django 5.1 was released and support for the deprecated settings was dropped entirely.

In my situation, I was receiving the file permissions issues because Django was reverting to the default file storage absent a proper configuration available:

By default, Django stores files locally, using the MEDIA_ROOT and MEDIA_URL settings. (docs)

The Fix

According to the Django 5.1 release notes, we need to change "DEFAULT_FILE_STORAGE" and "STATICFILES_STORAGE" over to "STORAGES." This value is a:

... dictionary containing the settings for all storages to be used with Django. It is a nested dictionary whose contents map a storage alias to a dictionary containing the options for an individual storage. (docs)

In order to map file storage (media) and static files, we'll do the following:

# app/cdn/conf.py

# DEFAULT_FILE_STORAGE = 'app.cdn.backends.MediaRootS3BotoStorage'
# STATICFILES_STORAGE = 'app.cdn.backends.StaticRootS3BotoStorage'
# ^^ deprecated Django => 4.2 & support removed Django >= 5.1; instead use:
STORAGES = {
    'default': {
        'BACKEND': 'app.cdn.backends.MediaRootS3BotoStorage'
    },
    'staticfiles': {
        'BACKEND': 'app.cdn.backends.StaticRootS3BotoStorage'
    }
}

In my case, these are settings I only want to use in production. In development, I'll use the file system so I'm not uploading test files to a production location nor needing to manage credentials in my development sandbox. Instead, I'll store these values in "app/cdn/conf.py" and import them in my "settings.py" file:

# settings.py

if not DEBUG:
    from ..cdn.conf import *

My settings file is nested in a "settings" directory, hence the double relative import.

With this change reflected in the project's settings, all is now well in the world.