You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django中按点赞数排序文章查询集,获取Top2最受欢迎文章

需求与问题描述

现有Article、Sentiment、Reaction三个模型,其中Sentiment的id为1代表点赞,id为2代表点踩,用户对文章的互动数据存在Reaction表中,模型定义如下:

# Reaction 模型
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篇文章,返回文章基础信息。当前编写的视图和序列化器无法正确统计点赞数并按降序排序,现有代码如下:

现有视图(views.py)

class MostPopularView(viewsets.ModelViewSet):
    articles = Reaction.objects.filter(sentiment=1).annotate(num_likes = Count('article_id')).order_by('num_likes')[:4]
    # queryset = Article.objects.filter(id=articles['article_id'])
#Doesn't work by hypothetically what I'm thinking
    for article in articles:
        queryset = Article.objects.filter(id=article['article_id'])
    serializer_class = MostPopularSerializer

现有序列化器(serializers.py)

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

URL配置

path('popular', views.MostPopularView.as_view({'get': 'list'}))

解决方案

1. 修正视图逻辑

直接对Article模型做注解统计,过滤出点赞相关的互动记录,再按点赞数降序取前2条:

from django.db.models import Count, Q
from rest_framework import viewsets

class MostPopularView(viewsets.ReadOnlyModelViewSet):
    serializer_class = MostPopularSerializer
    
    def get_queryset(self):
        # 给每个文章注解点赞数,仅统计sentiment=1的Reaction
        return Article.objects.annotate(
            num_likes=Count(
                'article_id',  # 对应Reaction中article_id的related_name
                filter=Q(article_id__sentiment__id=1),
                distinct=False
            )
        ).order_by('-num_likes')[:2]
  • 用ReadOnlyModelViewSet足够,因为只需要处理GET列表请求
  • Q对象精准过滤点赞记录,确保统计的是sentiment_id=1的互动
  • order_by('-num_likes')是降序排序,负号不能少
  • 不需要循环查询,一次注解就能完成统计+排序+筛选

2. 序列化器优化(可选)

如果要返回点赞数,给序列化器新增字段:

from rest_framework import serializers
from .models import Article

class MostPopularSerializer(serializers.ModelSerializer):
    num_likes = serializers.IntegerField()  # 新增点赞数字段
    
    class Meta:
        fields = ('id', 'title', 'tags', 'num_likes')
        model = Article

3. URL配置保持不变

原URL配置无需修改:

path('popular', views.MostPopularView.as_view({'get': 'list'}))

内容的提问来源于stack exchange,提问作者user14611431

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 11:01:23