Как смешивать Django, Uploadify и S3Boto Storage Backend?

Фон

Я делаю довольно большие загрузки файлов на Django. Размер файла обычно составляет 10 МБ-100 МБ.

Я нахожусь на Heroku, и я нажимаю на тайм-аут запроса 30 секунд.

Начало

Чтобы обойти предел, рекомендация Heroku должна загружаться из браузера DIRECTLY на S3.

Amazon документирует это, показывая вам, как написать HTML-форму для выполнения загрузки.

Поскольку я на Django, вместо того, чтобы писать HTML вручную, я использую django-uploadify-s3 (example). Это дает мне объект SWF, завернутый в JS, который выполняет фактическую загрузку.

Эта часть работает отлично! Ура!

Проблема

Проблема заключается в привязке данных к моей модели Django разумным способом. Сейчас данные возвращаются как простая строка URL, указывая на расположение файла.

Однако ранее я использовал S3 Boto из django-хранилищ для управления всеми моими файлами как FileFields, подкрепленные восхитительным S3BotoStorageFile.

Чтобы повторить, S3 Boto отлично работает изолированно, Uploadify отлично работает изолированно, проблема заключается в том, чтобы объединить два.

Я понимаю, что единственный способ заполнить FileField заключается в предоставлении имя_файла И файл содержание. Когда вы загружаете файлы из браузера в Django, это не проблема, поскольку Django имеет содержимое файла в буфере и может делать с ним все, что ему нравится. Тем не менее, при загрузке прямо на S3, как я, Django получает только имя файла и URL, а не двоичные данные, поэтому я не могу правильно заполнить FieldFile.

Cry для справки

Кто-нибудь знает грациозный способ использования S3Boto FileField в сочетании с прямой загрузкой S3?

Else, какой лучший способ управлять файлом S3 только на основе его URL-адреса? Включая истечение срока действия, идентификатор ключа и т.д.

Большое спасибо!

Ответы

Ответ 1

Используйте URLField.

Ответ 2

У меня была аналогичная проблема, когда я хочу хранить файл на s3 либо напрямую, используя FileField, либо у меня есть возможность для пользователя напрямую вводить URL. Чтобы обойти это, я использовал 2 поля в моей модели, один для FileField и один для URLField. И в шаблоне я мог бы использовать "или", чтобы увидеть, какой из них существует, и использовать его как {{instance.filefield или instance.url}}.

Ответ 3

Это не проверено, но вы должны иметь возможность использовать:

from django.core.files.storage import default_storage
f = default_storage.open('name_you_expect_in_s3', 'r')
#f is an instance of S3BotoStorageFile, and can be assigned to a field
obj, created = YourObject.objects.get_or_create(**stuff_you_know)
obj.s3file_field = f
obj.save()

Я думаю, что это должно установить локальный указатель на s3 и сохранить его, не перезаписывая содержимое.

ETA: вы должны сделать это только после того, как загрузка будет завершена на S3, и вы знаете ключ в s3.

Ответ 4

Оформить заказ django-filetransfers. Похоже, он играет хорошо с django-хранилищами.

Ответ 5

Я никогда не использовал django, поэтому ymmv:), но почему бы просто не написать один байт, чтобы заполнить контент? Таким образом, вы все равно можете использовать FieldFile.

Ответ 6

Я думаю, что писать фактический SQL может быть самым простым решением здесь. В качестве альтернативы вы можете подклассифицировать S3BotoStorage, переопределить метод _save и разрешить опцию kwarg пути к файлу, которая обойдена всем другим сохранением и просто возвращает очищенное имя.