Переход с Client-Django-S3 загрузки изображений/файлов на Client-S3 загрузку URL с предварительной подписью, сохраняя FileField/ImageField?

Текущее состояние нашего приложения следующее: Клиент делает POST-запрос на наш сервер приложений Django + DRF с одним или несколькими файлами, сервер django обрабатывает файлы, затем загружает и сохраняет их на S3. Это делается с помощью замечательных библиотек django-storages & boto3. В конечном итоге мы будем иметь ссылку url на наши файлы S3 в нашей Базе Данных.

Очень упрощенный пример выглядит следующим образом:

# models.py

class TestImageModel(models.Model):
    image = models.ImageField(upload_to='<path_in_bucket>', storage=S3BotoStorage())
# serializers.py

class TestImageSerializer(serializers.ModelSerializer):
    image = serializers.ImageField(write_only=True)

Библиотека storages обрабатывает загрузку на S3 и вызывает что-то вроде:

TestImageModel.objects.first().image.url

вернет ссылку на url изображения в S3 (технически в нашем случае это будет URL cloudfront, так как мы используем его как CDN, и установили custom_domain в классе S3BotoStorage)

Таков был первоначальный подход, но мы заметили большой расход памяти сервера из-за того, что изображения сначала загружаются на наш сервер, а затем снова загружаются на S3. Для эффективного масштабирования мы хотели бы перейти к подходу, при котором вместо этого изображения загружаются непосредственно с клиента на S3 с помощью заранее назначенных URL. Я нашел документацию о том, как это сделать, здесь: https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-presigned-urls.html.

Новая стратегия, которую я приму для загрузки изображений:

  1. Client requests Presigned url from Django API
  2. Client uploads to S3 directly
  3. Django updates reference to uploaded image in database with ImageField.

Мой вопрос касается 3). Как я могу сказать django record, что уже загруженное изображение в S3 должно быть местоположением ImageField, без необходимости повторной загрузки изображения через класс S3BotoStorage?

Альтернативой может быть изменение ImageField на URLField, и просто хранить ссылку нового изображения, но это не позволит мне использовать возможности ImageField (Forms в админке django, удаление непосредственно из S3 с помощью класса хранения .delete(), и т.д.).

Как я могу обновить ImageField, чтобы он указывал на существующий файл в том же хранилище, или есть лучший способ перейти к стратегии прямой загрузки Client-S3 с Django и ImageField?

Итак, очевидно, что вы можете просто сделать что-то вроде этого:

a = TestImageModel.objects.first()
a.image.name = 'path_to_image'
a.save()

И все прекрасно работает :)

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