Django sql命令

时间:2013-04-04 07:35:05

标签: sql database django django-queryset

我真的在这个问题上挣扎。 我需要能够根据评论中收到的积极投票数量对用户进行排序。

我有一个表userprofile,一个表注释和一个像likeComment的表。 表注释具有其用户创建者的外键,而表likeComment具有所关注注释的外键。 为了得到用户收到的肯定投票数,我做了:

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

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

谢谢

4 个答案:

答案 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,那么您需要将它们全部包含在SELECTGROUP 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位用户。