Хранилища Django + boto3 не работают. Сохранение статических файлов на локальном уровне при загрузке медиафайлов на S3
Я пытаюсь настроить проект django таким образом, чтобы статические файлы хранились в файловой системе, а медиафайлы загружались на amazon s3 bucket. Библиотека django storages получила обновление для django>4.2. Раньше это было просто, а теперь не работает с новыми настройками:
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATICFILES_STORAGE = 'django.core.files.storage.FileSystemStorage'
# Check if running in a production environment
STORAGES = {
'default': {
'BACKEND': 'storages.backends.s3boto3.S3Boto3Storage',
'OPTIONS': {
'bucket_name': os.getenv('AWS_STORAGE_BUCKET_NAME'),
'region_name': os.getenv('AWS_S3_REGION_NAME', 'us-east-1'),
'default_acl': 'public-read',
'file_overwrite': False,
'custom_domain': f'{os.getenv("AWS_STORAGE_BUCKET_NAME")}.s3.{os.getenv("AWS_S3_REGION_NAME", "us-east-1")}.amazonaws.com',
},
},
'staticfiles': {
'BACKEND': 'django.core.files.storage.FileSystemStorage',
'OPTIONS': {
'location': STATIC_ROOT,
},
}
}
# django-storages configuration for media files
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
MEDIA_URL = f'https://{os.getenv("AWS_STORAGE_BUCKET_NAME")}.s3.{os.getenv("AWS_S3_REGION_NAME", "us-east-1")}.amazonaws.com/media/'
При доступе к сайту с сервера статические файлы по-прежнему указывают на ведро s3, например:
us-east-1.amazonaws.com/media/admin/css/dark_mode.css
Это базовый css для админки django. Но почему он ищет файл в /media/?
I think you can get rid of Boto3 and use default storages.backends.s3.S3Storage backend, also you have to pass AWS keys either via options or environment variables. See below working code, but in my case storing both static and media files in Yandex S3.
ENDPOINT = 'storage.yandexcloud.net'
ENDPOINT_URL = 'https://' + ENDPOINT
STATIC_URL = f"{ENDPOINT_URL}/{env.str("BUCKET_NAME")}/static/"
MEDIA_URL = f"{ENDPOINT_URL}/{env.str("BUCKET_NAME")}/media/"
default_storage_backend = "storages.backends.s3.S3Storage"
default_storage_options = {
"access_key": env.str("YOS_ACCESS_KEY"),
"secret_key": env.str("YOS_SECRET_KEY"),
"bucket_name": env.str("BUCKET_NAME"),
"region_name": env.str("BUCKET_REGION"),
"endpoint_url": ENDPOINT_URL,
"custom_domain": f"{ENDPOINT}/{env.str('BUCKET_NAME')}",
"default_acl": 'public-read',
"querystring_auth": False,
"file_overwrite": True,
}
STORAGES = {
"staticfiles": {
"BACKEND": default_storage_backend,
"OPTIONS": {
**default_storage_options,
"location": "static",
}
},
"default": {
"BACKEND": default_storage_backend,
"OPTIONS": {
# add or override options defined in default
**default_storage_options,
"location": "media",
},
},
}
and environment:
YOS_ACCESS_KEY='...'
YOS_SECRET_KEY='...'
BUCKET_NAME=...
BUCKET_REGION=...
For AWS it should be:
"custom_domain": f"{env.str(BUCKET_NAME)}.{ENDPOINT}",
and
ENDPOINT = 's3.amazonaws.com'
ENDPOINT_URL = f"https://{env.str(BUCKET_NAME)}.{ENDPOINT}"
...
STATIC_URL = f"{ENDPOINT_URL}/static/"
MEDIA_URL = f"{ENDPOINT_URL}/media/"
I think you could leave your static as it is and change only default storage for media files.
I used https://forum.djangoproject.com/t/storage-4-2-how-to-subclass-default/29190/3 and official docs are here https://django-storages.readthedocs.io/en/stable/backends/amazon-S3.html