На момент выхода версии 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.