Хранилища 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/?
Думаю, можно избавиться от Boto3 и использовать стандартный бэкенд storages.backends.s3.S3Storage, также необходимо передать ключи AWS либо через опции, либо через переменные окружения. Смотрите ниже рабочий код, но в моем случае в 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",
},
},
}
и окружение:
YOS_ACCESS_KEY='...'
YOS_SECRET_KEY='...'
BUCKET_NAME=...
BUCKET_REGION=...
Для AWS это должно быть:
"custom_domain": f"{env.str(BUCKET_NAME)}.{ENDPOINT}",
и
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/"
Я думаю, что вы можете оставить статику как есть и изменить только хранилище по умолчанию для медиафайлов.
Я использовал https://forum.djangoproject.com/t/storage-4-2-how-to-subclass-default/29190/3, а официальная документация находится здесь https://django-storages.readthedocs.io/en/stable/backends/amazon-S3.html