Django使用template tag按likes排序博客文章出现重复条目问题
问题根本原因
你在对多对多字段likes直接排序时,Django ORM会自动对关联的点赞表执行JOIN操作,每一条点赞记录都会对应一行查询结果,所以有N个赞的帖子就会在结果中重复出现N次。你之前直接加distinct()无效,是因为排序的字段是多对多关联的likes,查询结果每一行的关联字段值都不同,distinct()无法识别为同一帖子,必须先把点赞数聚合成单个字段再排序,才能保证每个帖子只出现一次。
解决方案
不推荐把数据查询逻辑放到模板标签中处理,优先在视图层完成排序逻辑,符合Django MTV设计规范:
- 修改
views.py的查询逻辑,用annotate统计点赞数后再排序:
from django.db.models import Count def posts(request): # 按点赞数升序排序要降序的话把'likes_count'改成'-likes_count' posts = BlogPost.objects.filter(user=request.user)\ .annotate(likes_count=Count('likes'))\ .order_by('likes_count') context = {'posts': posts} return render(request, 'posts.html', context)
- 删掉模板中的排序过滤器,直接遍历即可:
{% load template_tags %} {% block content %} {% for post in posts %} {{post.title}} {% endfor %} {% endblock content %}
如果确实需要保留模板标签动态排序的能力,可以修改模板标签逻辑:
from django import template from django.db.models import Count register = template.Library() @register.filter def sort_by_likes(queryset, order='asc'): order_prefix = '-' if order == 'desc' else '' return queryset.annotate(likes_count=Count('likes'))\ .order_by(f'{order_prefix}likes_count')
模板调用示例:
{% for post in posts|sort_by_likes:'desc' %} {{post.title}} {% endfor %}
内容的提问来源于stack exchange,提问作者Van
相关产品推荐
相关产品推荐

