3

我有两个模型:

Base_Activity:
    some fields

User_Activity:
    user = models.ForeignKey(settings.AUTH_USER_MODEL)
    activity = models.ForeignKey(Base_Activity)
    rating = models.IntegerField(default=0) #Will be -1, 0, or 1

现在我想查询 Base_Activity,并对最对应的用户活动的项目进行排序,评分=1。我想做类似下面的查询,但该=1部分显然不起作用。

activities = Base_Activity.objects.all().annotate(
    up_votes = Count('user_activity__rating'=1),
).order_by(
    'up_votes'
)

我该如何解决这个问题?

4

1 回答 1

1

你不能这样使用Count,因为错误消息说:

SyntaxError:关键字不能是表达式

的参数Count必须是一个简单的字符串,例如user_activity__rating.

我认为一个很好的选择是使用AvgandCount一起:

activities = Base_Activity.objects.all().annotate(
    a=Avg('user_activity__rating'), c=Count('user_activity__rating')
).order_by(
    '-a', '-c'
)

活跃度最高的项目rating=1应该具有最高的平均数,在平均数相同的用户中,活跃度最高的用户会排名靠前。

如果您想排除有否决票的项目,请确保在 之后添加适当的filterorexclude操作annotate,例如:

activities = Base_Activity.objects.all().annotate(
    a=Avg('user_activity__rating'), c=Count('user_activity__rating')
).filter(user_activity__rating__gt=0).order_by(
    '-a', '-c'
)

更新

要获得所有项目,按他们的赞成票排序,不考虑反对票,我认为唯一的方法是使用原始查询,如下所示:

from django.db import connection

sql = '''
SELECT o.id, SUM(v.rating > 0) s
FROM user_activity o
JOIN rating v ON o.id = v.user_activity_id
GROUP BY o.id ORDER BY s DESC
'''
cursor = connection.cursor()
result = cursor.execute(sql_select)
rows = result.fetchall()

注意:不要硬编码模型的表名,而是从模型中获取表名,例如,如果您的模型被调用Rating,那么您可以使用Rating._meta.db_table.

我在 sqlite3 数据库上测试了这个查询,我不确定SUM那里的表达式在所有 DBMS 中都有效。顺便说一句,我有一个完美的 Django 站点来测试,我也使用 upvotes 和 downvotes。我使用一个非常相似的模型来计算赞成票和反对票,但我按sum值排序它们,stackoverflow 样式。该网站开源的,如果您有兴趣。

于 2013-10-18T18:19:16.970 回答