Как смешать Django, Uploadify и S3Boto Storage Backend? - PullRequest
14 голосов
/ 16 марта 2012

Фон

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

Я на Heroku, и у меня истекло время ожидания запроса 30 секунд.

Начало

Для того, чтобы обойти ограничение, рекомендация Heroku заключается в прямой загрузке из браузера на S3.

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

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

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

Проблема

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

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

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

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

Крик о помощи

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

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

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

Ответы [ 6 ]

1 голос
/ 29 октября 2013

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

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.

1 голос
/ 22 апреля 2012

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

1 голос
/ 19 марта 2012

Использовать URLField .

0 голосов
/ 02 июля 2013

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

0 голосов
/ 19 августа 2012

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

0 голосов
/ 16 марта 2012

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

...