我真的在这个问题上挣扎。 我需要能够根据评论中收到的积极投票数量对用户进行排序。
我有一个表userprofile,一个表注释和一个像likeComment的表。 表注释具有其用户创建者的外键,而表likeComment具有所关注注释的外键。 为了得到用户收到的肯定投票数,我做了:
LikeComment.objects.filter(Q(type = 1), Q(comment__user=user)).count()
现在我希望能够让所有用户按得票最多的用户排序。我怎么做 ?我尝试使用额外的和JOIN,但这没有去任何地方。
谢谢
答案 0 :(得分: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")
答案 1 :(得分:1)
models.py
class UserProfile(models.Model):
.........
def like_count(self):
LikeComment.objects.filter(comment__user=self.user, type=1).count()
views.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})
答案 2 :(得分:0)
Timmy's suggestion to use a subquery可能是解决此类问题的最简单方法,但子查询几乎从不像连接一样好,所以如果你有很多用户,你可能会发现你需要更好的性能。
所以,重新使用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
,那么您需要将它们全部包含在SELECT
和GROUP BY
子句中。)< / p>
Django的对象关系映射系统没有提供表达此查询的方法。 (据我所知 - 我会很高兴被告知其他! - 它只支持一个连接的聚合,而不是像这里的两个连接一样。)但是当ORM不能完成工作时,你可以随时运行raw SQL query,如下所示:
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
答案 3 :(得分:0)
我相信这可以通过Django的查询集来实现:
User.objects.filter(comments__likes__type=1)\
.annotate(lks=Count('comments__likes'))\
.order_by('-lks')
这里唯一的问题是这个查询会错过0赞的用户。来自@ gareth-rees,@ timmy-omahony和@Catherine的代码也将包含0位用户。