Упорядочение набора запросов по количеству экземпляров внешних ключей в поле 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 theUser
model [Django-doc] directly. For more information you can see the referencing theUser
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 theUser
model to theReaction
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 therelation touser
reactions
.