Django如何排序Tweet查询结果,将关注用户发布的内容排在前列
方案1:数据库层面排序(推荐,性能更好,适合数据量大的场景)
你不需要提前查询获取following列表,直接在ORM查询时通过条件注释实现排序,只需要一次数据库查询:
from django.db.models import Case, When, IntegerField # 先获取当前用户关注的用户id列表,比取完整User对象性能高 following_ids = UserFollow.objects.filter(user=request.user).values_list('user_id', flat=True) tweets = Tweet.objects.annotate( # 给关注用户发的推文标记优先级0,其他为1 sort_priority=Case( When(user_id__in=following_ids, then=0), default=1, output_field=IntegerField() ) # 先按优先级升序(0在前1在后),再按推文发布时间倒序,最新的排在前面 ).order_by('sort_priority', '-timestamp')
如果希望连following_ids的查询也合并到同一次查询,可以用跨表关联的条件:
from django.db.models import Case, When, BooleanField, Desc tweets = Tweet.objects.annotate( is_following_user=Case( # 利用UserFollow的反向关联判断,对应你模型中followers的related_name配置 When(user__followers__follower=request.user, then=True), default=False, output_field=BooleanField() ) ).order_by(Desc('is_following_user'), '-timestamp')
方案2:Python内存排序(适合已拿到推文列表、数据量小的场景)
如果你已经获取了tweets查询集和following用户列表,可以直接在Python层排序:
# 先把following转成集合,查找效率比列表高很多 following_set = set(following) # 排序规则:关注用户的推文在前,同优先级下最新发布的在前 sorted_tweets = sorted( tweets, key=lambda t: (0 if t.user in following_set else 1, -t.timestamp.timestamp()) )
额外优化建议
你原有获取关注用户列表的写法可以优化,无需遍历取出完整User对象,只取需要的id列表能减少内存消耗和IO开销:
# 优化前 following = [x.user for x in UserFollow.objects.filter(user=request.user)] # 优化后,仅取id following_ids = UserFollow.objects.filter(user=request.user).values_list('user_id', flat=True)
内容的提问来源于stack exchange,提问作者user12584812
相关产品推荐
相关产品推荐

