Хранилища 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

Вернуться на верх