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)和原始查询。
我目前正在尝试为 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)和原始查询。