我有两种模式:
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
部分显然无效。
activities = Base_Activity.objects.all().annotate(
up_votes = Count('user_activity__rating'=1),
).order_by(
'up_votes'
)
我该如何解决这个问题?
答案 0 :(得分:1)
您不能像这样使用Count
,因为错误消息显示:
SyntaxError:keyword不能是表达式
Count
的参数必须是一个简单的字符串,例如user_activity__rating
。
我认为一个好的选择可以是同时使用Avg
和Count
:
activities = Base_Activity.objects.all().annotate(
a=Avg('user_activity__rating'), c=Count('user_activity__rating')
).order_by(
'-a', '-c'
)
rating=1
次活动最多的项目应该具有最高的平均值,而在具有相同平均值的用户中,活动最多的项目将列在更高的位置。
如果您要排除有downvotes的项目,请务必在filter
之后添加相应的exclude
或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'
)
<强>更新强>
要获得所有项目,由他们的赞成商订购,无视downvotes,我认为唯一的方法是使用原始查询,如下所示:
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
,则可以使用{{1}获取其表名称}。
我在sqlite3数据库上测试了这个查询,我不确定Rating._meta.db_table
表达式是否适用于所有DBMS。顺便说一句,我有一个完美的Django网站进行测试,我也使用upvotes和downvotes。我使用一个非常相似的模型来计算upvotes和downvotes,但我按SUM
值stackoverflow样式对它们进行排序。如果您有兴趣,site为open-source。