-
Модель:
При создании новой записи через админку загружаемое изображение сохраняется под именем None.jpg. При редактировании записи и загрузке нового изображения его имя меняется на id объекта. Не хочу дважды загружать изображение, чтобы оно сохранялось-таки под <object-id>.jpg. Как это реализовать еще на этапе создания новой записи?class Entry(models.Model):
def get_thumb_upload_to(instance, filename):
return 'images/thumb/%s.jpg' % instance.id
thumb = models.ImageField(upload_to=get_thumb_upload_to)
text = models.textField() -
Простым способом - никак. Модель не знает своего id до сохранения. Соответственно либо сохраняйте 2 раза, либо делайте SELECT MAX(id) + 1
Но лучше придумайте другой способ именования файлов. -
Да, обычно в таких случаях проще использовать какой нить slug от title либо хеш от текста, но это смотря как часто модель будет меняться, возможно хеш это черезчур накладно будет. Хотя че там.
-
либо делайте SELECT MAX(id) + 1
Так лучше не делать, все таки. Модель не знает своего ID до сохранения не просто так. Если она выберет ID до сохранения, есть хорошая вероятность, что другая модель, сохраняющаяся в параллельной транзакции, выберет тот же ID, и тогда кто-нибудь из них сломается.
-
Спасибо за ответы. Остановлюсь на том, что поменяю привязку имени файла не к id объекта, а к slug.
Еще вопрос в ту же тему. С точки зрения концептуальности где правильнее делать ресайзинг изображения: в save_form_data в custom ImageField или в методе save модели? Кстати, в последнем случае проблемы с сохранением изображения под именем с идентификатором созданного объекта (<id>.jpg) нет. -
Точно неправильно делать это в save модели, потому что он вызывается гораздо чаще, чем меняется картинка. А перезаписывать картинку на каждый чих дорого.
save_form_dataнаверное подойдет, да. Только тогда надо будет позаботиться, чтобы все ваши кастомные формы, которые зачем-нибудь реализуют полностью свой алгоритм сохранения, тоже использовалиsave_form_data. Но это, в общем-то, не проблема. -
В save можно фильтровать данные, чтобы не пересохранять каждый вызов этого метода изображение, но пожалуй сделаю как положено - в save_form_data.
Кстати, а если я делаю на основе изображения его превью и хочу сохранить в другом поле той же модели, то какой метод нужно вызывать и как это реализовать в пределах моей реализации?class ThumbFileField(models.ImageField):
def __init__(self, thumb_field, **kwargs):
self.thumb_field = thumb_field
super(ThumbField, self).__init__(**kwargs)
def save_form_data(self, instance, data):
if data and isinstance(data, UploadedFile):
image = Image.open(data)
if image.mode != "RGB":
image = image.convert("RGB")
poster = image.resize(settings.THUMB_SIZE, Image.ANTIALIAS)
poster_field = getattr(instance, data.field_name)
# Удаляем старый файл
if poster_field.name != poster_field.field.default:
poster_field.storage.delete(poster_field.name)
# Возвращаем обработанное изображение
if isinstance(data, InMemoryUploadedFile):
thumb = StringIO()
poster.save(thumb, 'JPEG', quality=90)
data = InMemoryUploadedFile(thumb, data.field_name, data.name, data.content_type, thumb.len, data.charset)
elif isinstance(data, TemporaryUploadedFile):
file = data.temporary_file_path()
poster.save(file, 'JPEG', quality=90)
super(ThumbField, self).save_form_data(instance, data)
class Art(models.Model):
thumb = models.ImageField(verbose_name=u'Мини-постер',
upload_to=get_thumb_upload_to)
poster = models.ThumbFileField(thumb_field='thumb',
verbose_name=u'Постер',
upload_to=get_poster_upload_to) -
Можно еще взять sorl-thumbnail , где эти и 100 других вопросов уже решены.
-
Можно, но так я не научусь ничему.
-
Предпочитаю решать проблемы по ходу их поступления. Что-то осваивать без конкретной цели на будущее имхо тупиковый путь. Но у каждого свой путь самообразования :)
Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.

