Когда ваш проект на Django перерастает стадию разработки и переезжает на продакшн, хранение статических файлов и медиаконтента на локальном диске сервера становится проблемой. При использовании Docker, масштабировании приложения через несколько экземпляров или при смене сервера ваши файлы будут либо теряться, либо требовать сложной синхронизации.
Оптимальное решение — использовать объектное хранилище, совместимое с протоколом S3. В экосистеме Яндекса это Yandex Object Storage.
В этой статье мы разберем, как настроить Django для работы с Yandex S3, чтобы ваши изображения и CSS-файлы хранились в облаке и были доступны из любой точки мира.
Подготовка в консоли Yandex Cloud
Прежде чем переходить к коду, необходимо создать инфраструктуру в облаке:
- Создайте бакет. Бакет (bucket) — это логический контейнер для ваших файлов. Задайте ему уникальное имя и выберите подходящий класс хранения (обычно «Стандартный»).
- Создайте сервисный аккаунт. Создайте отдельного пользователя с ролью
storage.editor, чтобы Django имел права на запись и чтение файлов. - Получите статические ключи. В настройках сервисного аккаунта создайте «Статический ключ доступа». Вы получите
Access Key(ID) иSecret Key. Сохраните их сразу, так как секретный ключ показывается один раз.
Установка необходимых зависимостей
Для интеграции Django с S3 стандартом индустрии является библиотека django-storages, которая работает поверх boto3 (SDK для AWS S3, совместимого с Yandex Cloud).
Установите пакеты через pip:
pip install django-storages boto3
Настройка settings.py
Теперь перенесем конфигурацию в проект. Рекомендуется вынести все секретные данные в переменные окружения (например, используя python-dotenv).
1. Добавление приложения
Добавьте storages в список установленных приложений:
INSTALLED_APPS = [
# ...
'storages',
# ...
]
2. Конфигурация S3
Добавьте следующие параметры в ваш settings.py:
import os
# Настройки Yandex Object Storage
AWS_ACCESS_KEY_ID = os.getenv('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = os.getenv('AWS_SECRET_ACCESS_KEY')
AWS_STORAGE_BUCKET_NAME = os.getenv('AWS_STORAGE_BUCKET_NAME')
# URL-адрес эндпоинта Yandex Cloud (замените <id> на ID вашего облака)
AWS_S3_ENDPOINT_URL = f'https://storage.yandexcloud.net'
AWS_S3_REGION_NAME = 'ru-central1'
# Настройки для медиафайлов (пользовательский контент)
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
# Настройки для статики (CSS, JS, Images)
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
# Публичный доступ к файлам
AWS_S3_OBJECT_PARAMETERS = {
'CacheControl': 'max-age=86400',
}
Разделение статики и медиа
По умолчанию настройка выше сваливает всё в один бакет. В реальных проектах статику (код фронтенда) и медиа (загрузки пользователей) лучше разделять по разным папкам внутри бакета.
Для этого создайте два кастомных класса хранилища в файле storage_backends.py:
from storages.backends.s3boto3 import S3Boto3Storage
class StaticStorage(S3Boto3Storage):
location = 'static'
default_acl = 'public-read'
class MediaStorage(S3Boto3Storage):
location = 'media'
default_acl = 'public-read'
Затем обновите settings.py:
STATICFILES_STORAGE = 'my_project.storage_backends.StaticStorage'
DEFAULT_FILE_STORAGE = 'my_project.storage_backends.MediaStorage'
Сбор статики и проверка
Теперь, когда всё настроено, запустите команду сбора статики. Django соберет все файлы из папок static ваших приложений и отправит их напрямую в бакет Yandex Cloud:
python manage.py collectstatic
Если команда прошла успешно, вы увидите в консоли Yandex Cloud появившуюся папку static со всеми вашими ресурсами.
Возможные проблемы и их решение
- Ошибка 403 Forbidden: Проверьте права доступа сервисного аккаунта и убедитесь, что бакет настроен на публичное чтение, если вы хотите, чтобы пользователи видели картинки без специальных ссылок.
- Медленная загрузка: Используйте CDN (Content Delivery Network) перед S3, чтобы сократить задержки при доставке контента пользователям.
- Кэширование: Параметр
AWS_S3_OBJECT_PARAMETERSпозволяет управлять заголовкамиCache-Control, чтобы браузеры кэшировали статику и не запрашивали её при каждой перезагрузке страницы.
Заключение
Перенос статики и медиафайлов в Yandex Object Storage избавляет разработчика от проблем с локальным хранилищем и делает приложение готовым к горизонтальному масштабированию. Теперь ваши файлы хранятся надежно, независимо от того, сколько серверов или контейнеров запущено в вашем кластере.