1. alTus

    22.06.2009

    0 ↑
    0 ↓
    Здравствуйте!

    Упрощенно, есть 2 модели: товар и картинки к нему.
    class CatElement(models.Model):
    title = models.CharField(........)

    class CatPicture(models.Model):
    picture = ImageWithThumbnailsField(.......) # это поле из sorl
    element = models.ForeignKey('CatElement', blank=False, null=False)
    Задача в принципе тривиальная - вывод на страницу товаров с их картинками.
    Но надо, чтобы выводилась именно первая загруженная фотка (они грузятся через инлайн на странице товара) - то есть получается, что это фотка с наименьшим ID для данного товара.

    Объекты я получаю обычным CatElement.filter(**filters).order_by(....)

    И вопрос весь в том, как лучше эти связанные фотки получать.
    Хотелось бы объектами, т.к. у меня там превьюшки.

    Хороший ли вариант - выбрать все ID товаров данной страницы и сделать запрос с большим количеством OR: id=1 OR id=2 и так далее? (записей будет 10-20 на страницу)
    Мне кажется, как-то не очень.

    Получение в цикле связанных фоток отдельно для каждого товара тоже не очень хорошо.

    Размышляю в сторону запроса с джойном, но пока что-то ничего толкового не надумал.
  2. anonymous

    22.06.2009

    0 ↑
    0 ↓
    Мне кажется, как-то не очень.
    Отчего же, вполне вариант.

    Завести картинке дополнительное поле, которое помечает, что именно она будет показываться (например, is_featured). Потом:
    elements = CatElement.objects.filter(...).order_by(...)
    pictures = CatPicture.objects.filter(is_featured=True, pk__in=elements)
    Получится 1 запрос (правда с вложенным SELECT).
  3. Анонимно

    23.06.2009

    0 ↑
    0 ↓
    Да, дополнительное поле надо. Без него как-то не очень. И если есть потребность в порядке загрузок картинок не только для вышеописанного случая, я бы делал не BooleanField, а PositiveSmallIntegerField, куда бы и заносился порядок загрузки картинок.
  4. Михаил

    23.06.2009

    0 ↑
    0 ↓
    может в CatElement добавить поле main_picture = ForeignKey('CatPicture',....,null=True) и выставлять его в методе CatPicture.save. а ри выборке указывать select_related("CatPicture").
  5. alTus

    23.06.2009

    0 ↑
    0 ↓
    Спасибо, то что надо. Теперь о развитии событий :)

    Попробовал реализовать способ [от Михаила].

    Добавил ForeignKey в CatElement и переопределил метод save у модели (!)CatElement
        def save(self, force_insert=False, force_update=False):
    pic = self.catpicture_set.filter(element=self.id).order_by('id')[0:1]
    if pic and not pic[0] == self.picture:
    self.picture = pic[0]

    super(CatElement, self).save(force_insert, force_update)
    И тут 2 проблемы сразу:

    1) если у нас есть объект товара и для него например одна фотка, то если её удалить из инлайна этого товара, то удаляется и сам товар (как я понял - из-за того, что у этой фотки стоит foreignkey на этот товар и наоборот - сам товар ссылается теперь на фотку, и все связанные объекты удаляются автоматом)

    2) при самом первом добавлении товара его id неизвестен, и поэтому self.catpicture_set.filter(element=self.id).order_by('id')[0:1] ни к чему не приводит. можно ли без сигнала post_save обойтись? то есть именно в этом методе узнать id? пробовл super().save вызывать в начале но как-то не очень помогло.
  6. Михаил

    24.06.2009

    0 ↑
    0 ↓
    1) вообще обычно когда один ссылается на другого база на PostgreSQL не позволит так удалить. У вас какая база?
    2) непонятно где у вас self.catpicture_set.filter(element=self.id).order_by('id')[0:1] вызывается, в каком методе....
  7. alTus

    24.06.2009

    0 ↑
    0 ↓
    1) это сейчас на тестовом движке - sqlite соответственно. но мне казалось что база тут не при чем, ведь django по идее сам связанные удаляет, а не база за него это автоматом
    2) хм, ну я там вроде указал, что этот метод определен в модели CatElement (в файле models.py)

    —————

    может, кому пригодиться - сейчас я сделал через OR:
    это код вьюшки по объединению в один массив фоток и товаров.
    # получаем все фотки товаров данной страницы
    all_pictures = CatPicture.objects.filter(
    element__in=goods.object_list).order_by('id')
    # в словарь picrures накапливаем первые фотки
    # каждого товара; ключ массива - ID товара
    pictures = {}
    compare_id = False
    for pic in all_pictures:
    if compare_id == pic.element_id:
    continue
    pictures[pic.element_id] = pic.picture
    compare_id = pic.element_id

    # объединяем - доабавляем в каждый товар поле картинки
    full_object_list = []
    for item in goods.object_list:
    if item.id in pictures:
    item.main_pic = pictures[item.id]
    else:
    item.main_pic = False
    full_object_list += [item]

    goods.object_list = full_object_list
    Вопрос концептуальный, так сказать: всегда ли придется действовать так при передачe каких-то связанных данных в шаблон.
    Примеров миллион - например книги и авторы, которых надо выводить в списке - также мучиться с объединением? В PHP я делал просто связь по ID, но в django-шаблонах нельзя использовать конструкции типа authors[ID].
    Думается, все с этим сталкивались - какой тут django-way? )
  8. Кажется, вы пытаетесь заново изобрести select_related.

  9. alTus

    25.06.2009

    0 ↑
    0 ↓
    Разве?
    Насколько я понимаю, related был бы, если бы у меня была ссылка в CatElement на CatPicture.
    А у меня наоборот, в CatPicture стоит ForeinKey на CatElement.

    Да и вопрос теперь, в основном, не в том, как получить эти данные, а в том - как их в шаблон передавать (последний абзац моего предыдущего поста).

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