1. Поляк

    28.04.2009

    0 ↑
    0 ↓
    Модель:
    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()
    При создании новой записи через админку загружаемое изображение сохраняется под именем None.jpg. При редактировании записи и загрузке нового изображения его имя меняется на id объекта. Не хочу дважды загружать изображение, чтобы оно сохранялось-таки под <object-id>.jpg. Как это реализовать еще на этапе создания новой записи?
  2. anonymous

    28.04.2009

    0 ↑
    0 ↓
    Простым способом - никак. Модель не знает своего id до сохранения. Соответственно либо сохраняйте 2 раза, либо делайте SELECT MAX(id) + 1

    Но лучше придумайте другой способ именования файлов.
  3. Анонимно

    28.04.2009

    0 ↑
    0 ↓
    Да, обычно в таких случаях проще использовать какой нить slug от title либо хеш от текста, но это смотря как часто модель будет меняться, возможно хеш это черезчур накладно будет. Хотя че там.
  4. Иван Сагалаев

    29.04.2009

    0 ↑
    0 ↓

    либо делайте SELECT MAX(id) + 1

    Так лучше не делать, все таки. Модель не знает своего ID до сохранения не просто так. Если она выберет ID до сохранения, есть хорошая вероятность, что другая модель, сохраняющаяся в параллельной транзакции, выберет тот же ID, и тогда кто-нибудь из них сломается.

  5. Поляк

    29.04.2009

    0 ↑
    0 ↓
    Спасибо за ответы. Остановлюсь на том, что поменяю привязку имени файла не к id объекта, а к slug.

    Еще вопрос в ту же тему. С точки зрения концептуальности где правильнее делать ресайзинг изображения: в save_form_data в custom ImageField или в методе save модели? Кстати, в последнем случае проблемы с сохранением изображения под именем с идентификатором созданного объекта (<id>.jpg) нет.
  6. Иван Сагалаев

    29.04.2009

    0 ↑
    0 ↓

    Точно неправильно делать это в save модели, потому что он вызывается гораздо чаще, чем меняется картинка. А перезаписывать картинку на каждый чих дорого.

    save_form_data наверное подойдет, да. Только тогда надо будет позаботиться, чтобы все ваши кастомные формы, которые зачем-нибудь реализуют полностью свой алгоритм сохранения, тоже использовали save_form_data. Но это, в общем-то, не проблема.

  7. Поляк

    29.04.2009

    0 ↑
    0 ↓
    В 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)
  8. redbaron

    03.05.2009

    0 ↑
    0 ↓
    Можно еще взять sorl-thumbnail , где эти и 100 других вопросов уже решены.
  9. Поляк

    04.05.2009

    0 ↑
    0 ↓
    Можно, но так я не научусь ничему.
  10. redbaron

    04.05.2009

    0 ↑
    0 ↓
    Предпочитаю решать проблемы по ходу их поступления. Что-то осваивать без конкретной цели на будущее имхо тупиковый путь. Но у каждого свой путь самообразования :)

Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.