Загрузка файлов в Django. FileField & upload_to. 1
На момент выхода версии 1.0 Django, одним из самых значительных изменений стал механизм загрузки (upload) и хранения (storage) файлов. Загрузка файлов без FileField в модели базы данных конечно очень редкий случай, поэтому начнем именно с одного из обязательных параметров FileField — upload_to.
Главная инновация — это гибкая возможность настройки этого самого upload_to. Раньше можно было только передавать строку
с кодированными strftime параметрами. Тем самым можно было разбивать
загруженные файлы по директориям, создаваемыми по дате, типа uploads/mp3/2008-12/uploaded.mp3. Сейчас параметром
upload_to может быть и callable, т.е. к примеру функция, которая должна возвращать полный путь с именем файла, куда
будет сохраняться загруженный файл. Функция должна принимать два параметра: instance и filename.
- instance — это экземпляр объекта модели, которой и принадлежит поле с типом FileField.
- filename — юникодное имя файла.
Эта функция будет запускаться перед сохранением в базу, поэтому если объект новый (вы не редактируете существующий объект, а создаете новый), то поле pk/id будет пустым и соотвественные Django сигналы еще не выполнены.
Думаю, что с примером кода все будет наиболее хорошо понятно.
Итак функция-callback, которую мы будем использовать в upload_path:
def make_upload_path(instance, filename):
"""Generates upload path for FileField"""
return u"uploads/%s/%s" % (instance.category.slug, filename)
Теперь пример модели с FileField:
class Upload(models.Model):
user = models.ForeignKey(User)
file = models.FileField(upload_to=make_upload_path)
category = models.ForeignKey(Category)
uploaded_date = models.DateTimeField(auto_now_add=True)
Все просто. Можно использовать множество параметров вашей модели для создания директорий
и упорядочивания файлов в них. И самое главное upload_to — самый простой способ
закачивания файлов с русскими (и другими юникодными) именами. Т.к. по-умолчанию
Django заменяет их на символ подчеркивания, что приводит к появлению файлов типа __________.jpg.
Если вы сделаете самую простую функцию с вовращением вида return u"uploads/mypath/%s" % (filename),
то получите русские имена файлов после закачки.
Официальная документация Django по FileField.
FileField в Django, проблемка с удалением
Есть проблема в Django с удалением файла в FileField и ImageField из админки. Проблема давняя, а до сих пор не решенная, недавно вернулись к её обсуждению. Вот патч лежит уже три месяца как. Вчера вроде по нему появилась активность. Посмотрим…
Вот старый тикет #22 (его закрыли) и новый #2534 с более “умным” патчем.
А от себя скажу, что в модели файл получается удобнее хранить в отдельной таблице, в большинстве случаев. Т.к. при удалении ссылающегося на него объекта, сам файл можно оставить и потом использовать опять (если файл большой, то каждый раз его заливать неудобно при удалении/добавлении зависящего объекта); да плюс обычно хранится не тупо неизвестный binary файл, а что-то более интересное, нуждаещееся в описании и какой-то мета-информации, следовательно удобно было бы потом делать расширенное описание файла добавлением новых полей в таблицу по мере необходимости.
И если брать частный случай с Django, то тогда файл можно легко удалить как отдельный эелемент модели.






