1

我真的在这方面苦苦挣扎。我需要能够按对他们的评论收到的正面投票数对我的用户进行排序。

我有一个表 userprofile、一个表评论和一个表 likeComment。表评论对其用户创建者有一个外键,而表 likeComment 有一个对喜欢的评论的外键。为了获得用户收到的正面投票数,我这样做:

LikeComment.objects.filter(Q(type = 1), Q(comment__user=user)).count()

现在我希望能够让所有用户按投票最多的用户排序。我怎么做 ?我尝试使用 extra 和 JOIN 但这并没有去任何地方。

谢谢

4

4 回答 4

2

听起来您想对注释执行过滤器:

class User(models.Model):
     pass

class Comment(models.Model):
    user = models.ForeignKey(User, related_name="comments")

class Like(models.Model):
    comment = models.ForeignKey(Comment, related_name="likes")
    type = models.IntegerField()

users = User \
    .objects \
    .all()
    .extra(select = {
        "positive_likes" : """
        SELECT COUNT(*) FROM app_like
        JOIN app_comment on app_like.comment_id = app_comment.id
        WHERE app_comment.user_id = app_user.id AND app_like.type = 1 """})
    .order_by("positive_likes")
于 2013-04-04T08:20:08.080 回答
1

模型.py

class UserProfile(models.Model):
    .........

    def like_count(self):
        LikeComment.objects.filter(comment__user=self.user, type=1).count()

视图.py

def getRanking( anObject ):
    return anObject.like_count()

def myview(request):
    users = list(UserProfile.objects.filter())
    users.sort(key=getRanking, reverse=True)       
    return render(request,'page.html',{'users': users})
于 2013-04-04T07:50:11.270 回答
0

Timmy 建议使用子查询可能是解决此类问题的最简单方法,但子查询的性能几乎没有联接好,因此如果您有很多用户,您可能会发现您需要更好的性能。

因此,重新使用 Timmy 的模型:

class User(models.Model):
     pass

class Comment(models.Model):
    user = models.ForeignKey(User, related_name="comments")

class Like(models.Model):
    comment = models.ForeignKey(Comment, related_name="likes")
    type = models.IntegerField()

您想要的查询在 SQL 中如下所示:

SELECT app_user.id, COUNT(app_like.id) AS total_likes
FROM app_user
LEFT OUTER JOIN app_comment
             ON app_user.id = app_comment.user_id
LEFT OUTER JOIN app_like
             ON app_comment.id = app_like.comment_id AND app_like.type = 1
GROUP BY app_user.id
ORDER BY total_likes DESCENDING

(如果您的实际User模型有更多字段id,那么您需要将它们全部包含在SELECTandGROUP BY子句中。)

Django 的对象关系映射系统没有提供表达这个查询的方法。(据我所知——如果不是这样,我很高兴被告知!——它只支持跨一个连接的聚合,而不是像这里那样跨两个连接的聚合。)但是当 ORM 不能完全胜任这项工作时,你始终可以运行原始 SQL 查询,如下所示:

sql = '''
    SELECT app_user.id, COUNT(app_like.id) AS total_likes
    # etc (as above)
'''
for user in User.objects.raw(sql):
    print user.id, user.total_likes
于 2013-04-04T10:07:22.773 回答
0

我相信这可以通过 Django 的查询集来实现:

User.objects.filter(comments__likes__type=1)\
    .annotate(lks=Count('comments__likes'))\
    .order_by('-lks')

这里唯一的问题是这个查询会错过点赞数为 0 的用户。来自 @gareth-rees、@timmy-omahony 和 @Catherine 的代码也将包括排名为 0 的用户。

于 2013-04-04T15:12:51.537 回答