Ваша помощь будет оценена по достоинству! Спасибо.

Я создаю сайт, который отображает фотоальбомы. Для этого у меня есть следующие модели.

class Medium(models.Model):
    pass

class MediaSet(models.Model):
    media = models.ManyToManyField("Medium", related_name="sets", through="SetContent", through_fields=('set', 'medium'),)

class SetContent(models.Model):
    is_cover = models.BooleanField(default=None, null=True)
    set = models.ForeignKey("MediaSet", on_delete=models.CASCADE, related_name="set_content")
    medium = models.ForeignKey("Medium", on_delete=models.CASCADE, related_name="set_contents")

У каждого медиасета (=альбома) может быть обложка. Если нет, то я просто использую первое попавшееся изображение.

Теперь я пытаюсь оптимизировать БД путем сокращения запросов. Я работаю над MediaSetListView, который перечисляет медиа-наборы. Возможно ли на уровне запроса аннотировать или Prefetch() обложку (один Medium) в зависимости от того, существует ли is_cover или нет?

Другими словами: Получить список всех медиасетов и добиться, чтобы каждый медиасет имел обложку, которая является либо носителем, отмеченным как "is_cover" в SetContent, либо первым носителем в SetContent.

В настоящее время у меня есть эта логика в модели, но это приводит к тоннам запросов, которые мне не нужны.

Спасибо за помощь.

Как насчет добавления ссылки на обложку в класс MediaSet и использования декоратора свойств? Это избавит вас от лишней колонки в таблице manytomany, и я предполагаю, что у вас никогда не будет больше одной обложки на альбом, верно? Тогда это отношение должно быть отражено в классе MediaSet, на мой взгляд. Тогда, кстати, вы могли бы избавиться и от класса SetContent

class MediaSet(models.Model):
    _cover = models.ForeignKey("Medium", blank=true, null=true, on_delete=models.SET_NULL)
    media = models.ManyToManyField("Medium", related_name="albums")
    
    @property
    def cover(self):
        if self._cover:
            return self._cover
        else:
            return self.media.first()  

    @cover.setter
    def cover(self, value):
        self._cover = value
Вернуться на верх