在Django中使用django-comments-xtd,如何返回排序后的最多评论文章?
解决Django查询评论最多文章的排序问题
问题核心是Post.published.filter(pk__in=post_ids)不会保留post_ids的原有顺序,数据库默认会按自身规则(如主键升序)返回结果。要让文章保持评论数从高到低的排序,可通过以下两种方式解决:
方案一:数据库层面自定义排序(推荐)
利用Django的Case和When构建排序规则,直接在数据库完成排序,性能更优:
from django.db.models import Case, When @register.simple_tag def getMostCommentedPosts(count=5): content_type = ContentType.objects.get_for_model(Post) comment_counts = XtdComment.objects.values('object_pk').annotate(comment_count=Count('object_pk')).order_by('-comment_count')[:count] post_ids = [comment['object_pk'] for comment in comment_counts] # 为每个post_id分配对应位置序号,按该序号排序 ordering = Case(*[When(pk=pk, then=pos) for pos, pk in enumerate(post_ids)]) return Post.published.filter(pk__in=post_ids).order_by(ordering)
原理
Case和When会根据post_ids的顺序,为每个文章主键分配一个递增的序号,再通过order_by让结果按这个序号升序排列,完美匹配评论数从高到低的顺序。
方案二:内存手动排序(适合小数据量)
将查询结果转为列表后,手动按post_ids的顺序重新排序:
@register.simple_tag def getMostCommentedPosts(count=5): content_type = ContentType.objects.get_for_model(Post) comment_counts = XtdComment.objects.values('object_pk').annotate(comment_count=Count('object_pk')).order_by('-comment_count')[:count] post_ids = [comment['object_pk'] for comment in comment_counts] posts = list(Post.published.filter(pk__in=post_ids)) # 按post_ids的索引位置排序 posts.sort(key=lambda x: post_ids.index(x.pk)) return posts
优缺点
- 代码直观,但
list.index()是O(n)操作,数据量大时效率较低,仅适合少量数据场景。
内容的提问来源于stack exchange,提问作者Owl66
相关产品推荐
相关产品推荐

