Django,如何在单个查询集中进行多个注释

Django, How to make multiple annotate in a single queryset

我目前正在尝试为 Django 中的用户模型注释两个不同数量的点赞。

这是我用于 return 所需查询集的代码

def get_top_user(self):
    return User.objects. \
        annotate(guide_like=Count('guidelike')).\
        annotate(news_like=Count('newslike')).\
        values_list('first_name', 'last_name', 'guide_like','news_like').\
        order_by('-guide_like')

然而,querySet returns ["Bob", "Miller", 612072, 612072]。如您所见,Django 获取两个注释值并将它们相乘,这就是我得到 612072 的原因。

有没有办法在单个查询集中调用多个注释而不获取这些乘积值。

编辑:还尝试在查询末尾添加 distinct() 或在每个计数中添加 distinct=True 但调用只会进入无限循环。

这就是 django annotate 生成 sql 代码的方式:它执行所有必要的连接,然后对所有用户字段进行分组,并使用注释函数(在您的情况下计数)进行聚合。因此,它将用户与他们所有喜欢的指南连接起来,然后加入所有喜欢的新闻,然后简单地计算每个用户产生的行数。

如果可以,您应该使用raw querysets, or extra 查询集方法。例如:

User.objects.all().extra(select={
    'guide_likes': 'select count(*) from tbl_guide_likes where user_id=tbl_users.id',
    'news_like': 'select count(*) from tbl_news_likes where user_id=tbl_users.id'
}).\
values_list('first_name', 'last_name', 'guide_like','news_like')

为了更加灵活,您可以使用 extra 方法的 select_params 参数来提供表的名称(您可以通过 Model._meta 获得)。顺便说一下,这是一种非常不方便和老套的方法。 迟早你的逻辑会变得更加复杂,然后你应该将它从 python 代码中删除到 sql(存储 functions/procedures)和原始查询。