Django ignores static configuration for uploading to S3
I had the same problem with media files before, I did all the configuration but django kept saving the media files locally and not in S3, I think it was solved by implementing a custom class inheriting from S3Boto3Storage. Now I want to save my static files in the same S3 but I have the same problem, django completely ignores my configuration and keeps saving the files locally in the staticfiles directory.
These are my installed apps
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'storages',
'app',
'crispy_forms',
'crispy_bootstrap5',
]
Media file setup currently working:
AWS_ACCESS_KEY_ID = config('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = config('AWS_SECRET_ACCESS_KEY')
AWS_STORAGE_BUCKET_NAME = config('AWS_STORAGE_BUCKET_NAME')
AWS_S3_ENDPOINT_URL = config('AWS_S3_ENDPOINT_URL')
AWS_S3_OBJECT_PARAMETERS = {
'CacheControl': 'max-age=86400',
}
AWS_MEDIA_LOCATION = 'media'
AWS_S3_REGION_NAME = config('AWS_S3_REGION_NAME')
AWS_DEFAULT_ACL = 'public-read'
AWS_QUERYSTRING_AUTH = False
AWS_S3_CONNECTION_TIMEOUT = 60
MEDIA_URL = f"https://{AWS_STORAGE_BUCKET_NAME}.{AWS_S3_REGION_NAME}.digitaloceanspaces.com/{AWS_MEDIA_LOCATION}/"
PUBLIC_MEDIA_LOCATION = 'media'
DEFAULT_FILE_STORAGE = 'cms.storage_backends.PublicMediaStorage'
DEFAULT_PROFILE_PHOTO=config('DEFAULT_PROFILE_PHOTO')
Static file configuration, the idea is to read CMS_STATIC_LOCAL_STORAGE from the environment variables, but for testing purposes the value is set constantly:
CMS_STATIC_LOCAL_STORAGE = False
print('Static Local Storage: ', CMS_STATIC_LOCAL_STORAGE)
AWS_STATIC_LOCATION = 'static'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
if CMS_STATIC_LOCAL_STORAGE:
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]
else:
STATIC_URL = f"https://{AWS_S3_REGION_NAME}.digitaloceanspaces.com/{AWS_STORAGE_BUCKET_NAME}/{AWS_STATIC_LOCATION}/"
STATICFILES_STORAGE = 'cms.storage_backends.StaticStorage'
Please note that I have also already tried setting it like this STATIC_URL = f"https://{AWS_STORAGE_BUCKET_NAME}.{AWS_S3_REGION_NAME}.digitaloceanspaces.com/{AWS_STATIC_LOCATION}/"
The storage_backends.py file:
from storages.backends.s3boto3 import S3Boto3Storage
class PublicMediaStorage(S3Boto3Storage):
location = 'media'
default_acl = 'public-read'
file_overwrite = False
@property
def querystring_auth(self):
return False
class StaticStorage(S3Boto3Storage):
location = 'static'
default_acl = 'public-read'
I swear this problem is driving me crazy, I've been trying to solve it for hours. As I told you, the same thing happened to me with the media files and I think I solved it with the custom class, but in the case of the static files I can't find a solution anywhere.
(env) msi@fedora ~/Escritorio/django_cms develop ± ./manage.py collectstatic --no-input
Running server with DEBUG=False and ALLOWED_HOSTS=['localhost']
Static Local Storage: False
At first I tried to make the settings dynamically according to the CMS_STATIC_LOCAL_STORAGE variable, but I even tried to do it directly and got the same result. I also tried to put the STATIC_ROOT declaration inside the if true of CMS_STATIC_LOCAL_STORAGE, but I got an error on the console that is the following:
(env) msi@fedora ~/Escritorio/django_cms develop ± ./manage.py collectstatic --no-input
Running server with DEBUG=False and ALLOWED_HOSTS=['localhost']
Static Local Storage: False
Traceback (most recent call last):
File "/home/msi/Escritorio/django_cms/./manage.py", line 22, in <module>
main()
...
...
File "/home/msi/Escritorio/django_cms/env/lib/python3.11/site-packages/django/contrib/staticfiles/storage.py", line 39, in path
raise ImproperlyConfigured(
django.core.exceptions.ImproperlyConfigured: You're using the staticfiles app without having set the STATIC_ROOT setting to a filesystem path.
UPDATE Testing I realized that the frontend is already redirecting to Digital Ocean's S3, but when doing the collectstatic it continues saving in my local, therefore the frontend is not rendered correctly.
I probably have the same issue. Have you upgraded to Django 5.1 recently?
S3 configured as always, but default_storage.url()
is now returning local URLs in Django 5.1.
$ python manage.py shell
Python 3.10.0
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.conf import settings
>>> settings.DEFAULT_FILE_STORAGE
'storages.backends.s3boto3.S3Boto3Storage'
>>> from django.core.files.storage import default_storage
>>> default_storage.url('subfolder/dummyfile.txt')
>>> 'subfolder/dummyfile.txt' (instead of https://{}.s3.amazonaws.com/subfolder/dummyfile.txt?signature...)
It seems that the support for Django 5.1 was added a few days ago to master branch, not yet in pip.
You can:
- a) downgrade from Django 5.1 to 5.0 (for me it works again)
- b) try to add the latest commit
https://github.com/jschneier/django-storages/commit/0fc0650a3a2ba5ac088b127d7771634a26f2793c
to your requirements.txt to load the latest version (doesn't work for me)