Упорядочение набора запросов по количеству экземпляров внешних ключей в поле Django

Я пытаюсь вернуть объекты, относящиеся к сквозной таблице, которая подсчитывает количество реакций на запись в блоге.

У меня есть модель статьи, модель настроения и модель реакций. Сентимент - это просто 1 или 2, 1 представляет like и 2 для dislike. На фронтенде пользователи могут реагировать на статью, и их реакции хранятся в таблице Reactions.

Reactions model

class Reaction(models.Model):
    user_id = models.ForeignKey(User, related_name='user_id', on_delete=models.CASCADE)
    article_id = models.ForeignKey(Article, related_name='article_id', on_delete=models.CASCADE)
    sentiment = models.ForeignKey(Sentiment, related_name='sentiment', on_delete=models.CASCADE)

Я хочу найти 2 наиболее понравившиеся статьи, поэтому я написал представление для обработки GET запроса

views.py

class MostPopularView(generics.RetrieveAPIView):
    queryset = Reaction.objects.annotate(num_likes = Count('sentiment_id')).order_by('num_likes')
    serializer_class = MostPopularSerializer

и сериализатор для преобразования данных

serializers.py

class MostPopularSerializer(serializers.Serializer):
    class Meta:
        fields = (
            'id',
            'title',
        )
        model = Article

В том виде, в котором код существует сейчас, я получаю ответ

<QuerySet [<Reaction: d745e09b-5685-4592-ab43-766f47c73bef San Francisco Bay 1>, <Reaction: d745e09b-5685-4592-ab43-766f47c73bef The Golden Gate Bridge 1>, <Reaction: dd512e6d-5015-4a70-ac42-3afcb1747050 San Francisco Bay 1>, <Reaction: dd512e6d-5015-4a70-ac42-3afcb1747050 The Golden Gate Bridge 2>]>

Показано San Francisco Bay имеет 2 симпатии и The Golden Gate Bridge имеет 1 симпатию и 1 антипатию.

Я пробовал несколько методов, чтобы получить правильный ответ, включая фильтрацию по sentiment=1, но не могу продвинуться дальше этого. Я ищу способ подсчитать количество полей sentiment=1, которые соответствуют каждой статье id и упорядочить их в порядке убывания, так, чтобы наиболее понравившиеся были наверху.

Спасибо

Я решил похожую проблему другим способом. Мне нужно было отсортировать набор запросов Person по тому, как часто использовалась страна.

Я добавил свойство в Модель

class Country(models.Model):
    .
    .
    def _get_count(self):
        count = len(Person.objects.filter(country=self.id))

        return count or 0

    count = property(_get_count)

В представлении у меня есть этот набор запросов

qs = sorted(Country.objects.all(), key=lambda country: country.count*-1)

Мне нужно было использовать python sorted, потому что django qs.order_by не может сортировать по свойствам. *-1 используется для сортировки по убыванию

Бессмысленно использовать Reaction в качестве кверисета, вы используете Article в качестве кверисета, так:

from django.db.models import Case, Value, When


class MostPopularView(generics.RetrieveAPIView):
    queryset = Article.objects.annotate(
        sentiment=Sum(
            Case(
                When(article_id__sentiment_id=1, then=Value(1)),
                When(article_id__sentiment_id=2, then=Value(-1)),
            )
        )
    ).order_by('-sentiment')
    serializer_class = MostPopularSerializer

Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.


Примечание: Обычно не добавляют суффикс …_id к полю ForeignKey, так как Django автоматически добавит поле-"близнец" с суффиксом …_id. Поэтому он должен быть user, вместо user_id.

.

Note: The related_name=… parameter [Django-doc] is the name of the relation in reverse, so from the User model to the Reaction model in this case. Therefore it (often) makes not much sense to name it the same as the forward relation. You thus might want to consider renaming the user relation to reactions.

Вернуться на верх