Можно ли добавить изображения из ведра AWS S3 в базу данных Wagtail/Django из , без загрузки и открытия каждого файла?
У меня есть уже существующее ведро AWS S3, которое я хочу использовать для Wagtail Images. Я хочу заполнить галерею изображениями, хранящимися в ведре S3, чтобы они были доступны для полей изображений в моделях страниц, а также для встроенных изображений RichText.
Проблема в том, что есть 1500 изображений, поэтому я думаю, что хочу избежать того, чтобы скрипт фактически загружал/открывал каждый из этих файлов, если это возможно; я беспокоюсь, что это заставит скрипт работать долгое время и может убить сервер с небольшим количеством памяти
Есть ли способ зарегистрировать файлы в базе данных без фактического открытия каждого изображения?
Где я нахожусь
Как я думаю, мне нужно вручную получить ссылки на файлы с помощью boto, а затем каким-то образом подключить эти ссылки к базе данных?
s3_client = boto3.client('s3', aws_access_key_id=settings.AWS_S3_ACCESS_KEY_ID, aws_secret_access_key=settings.AWS_S3_SECRET_ACCESS_KEY)
items = s3_client.list_objects_v2(Bucket='xxx')
for item in items:
image = CMSImage(...)
Но что дальше, я не уверен. Я вижу решения, которые включают загрузку/открытие файлов , но есть ли способ сделать это без этого?
Я не смог остановить загрузку файлов Wagtail, поскольку ему необходимо определить размеры изображения, но я смог остановить загрузку дубликатов оригинальных изображений. С помощью приведенного ниже решения оригинальные ключи файлов S3 используются Wagtail.
(Конечно, рендеры по-прежнему создаются и добавляются в ведро S3 в соответствии с обычными операциями Wagtail)
Вот как я это сделал:
- Для каждого ключа файла S3, который я хотел импортировать (например, взятого из
boto3
запроса, как показано в примере кода ниже), создайте экземпляр djangoFile
.
- Присоедините
File
к новой модели wagtail Image ( после создания модели) - Крупно говоря, определите
image.file._committed = True
для предотвращения повторной загрузки . Это противодействует логике по умолчанию класса FileField для сохранения и загрузки вновь присоединенных файлов.
Полный код:
import boto3
from wagtail.images.models import Image
# Loop through images in an S3 bucket
s3_client = boto3.client('s3', aws_access_key_id=settings.AWS_S3_ACCESS_KEY_ID, aws_secret_access_key=settings.AWS_S3_SECRET_ACCESS_KEY)
items = s3_client.list_objects_v2(Bucket='xxx')
for item in items:
# get a `File` instance for each image
s3_file = default_storage.open(file_name)
# prepare a new wagtail `Image` instance
image = Image(title=file_name)
# attach the `File` after `Image` instantiation
image.file = s3_file
# prevent re-upload
image.file._committed = True
# Wagtail will generate some renditions and so on, but won't re-upload the original file :)
image.save()
Я не смог остановить загрузку файлов Wagtail, поскольку ему необходимо определить размеры изображения, но я смог остановить загрузку дубликатов оригинальных изображений. С помощью приведенного ниже решения оригинальные ключи файлов S3 используются Wagtail.
(Конечно, рендеры по-прежнему создаются и добавляются в ведро S3 в соответствии с обычными операциями Wagtail)
Вот как я это сделал (с интеграцией S3 от django-storage в фоновом режиме):
- Получите экземпляр django
File
из удаленного хранилища через API хранилища Django. - Присоедините этот
File
из хранилища к новому экземпляру wagtail Image, после создания экземпляра .
- Крупно говоря, установите
image.file._committed = True
для предотвращения повторной загрузки. Это противодействует логике по умолчанию класса FileField для сохранения и загрузки вновь присоединенных файлов.
Полный код:
import boto3
from wagtail.images.models import Image
# Loop through images in an S3 bucket
s3_client = boto3.client('s3', aws_access_key_id=settings.AWS_S3_ACCESS_KEY_ID, aws_secret_access_key=settings.AWS_S3_SECRET_ACCESS_KEY)
items = s3_client.list_objects_v2(Bucket='xxx')
for item in items:
# get a `File` instance for each image
s3_file = default_storage.open(file_name)
# prepare a new wagtail `Image` instance
image = Image(title=file_name)
# attach the `File` after `Image` instantiation
image.file = s3_file
# prevent re-upload
image.file._committed = True
# Wagtail will generate some renditions and so on, but won't re-upload the original file :)
image.save()