【问题标题】:Django, How to make multiple annotate in a single querysetDjango,如何在单个查询集中进行多个注释
【发布时间】:2015-09-03 05:10:29
【问题描述】:

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

这是我用来返回所需查询集的代码

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 返回 ["Bob", "Miller", 612072, 612072]。如您所见,Django 获取两个注释值并将它们相乘,这就是我得到 612072 的原因。

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

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

【问题讨论】:

  • 唯一的解决方案是添加 distinct=True 这不是一个好的做法,在我的情况下不起作用。
  • 你能展示 GuideLike 和 NewsLike 模型吗?
  • 另外,请分别显示 guide_like 和 news_like 注释调用的结果
  • @Jean-MichelProvencher 我实际上遇到了这个问题,distinct 解决了它。为什么你说这不是一个好习惯?

标签: python django count django-queryset annotate


【解决方案1】:

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

如果可以,您应该使用raw querysetsextra Queryset 方法。例如:

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(存储函数/过程)和原始查询。

【讨论】:

  • 非常感谢!最后决定简单地将我的多个查询拆分为单个查询,因为它们响应时间太长。
猜你喜欢
  • 1970-01-01
  • 2019-12-30
  • 1970-01-01
  • 2014-12-22
  • 2017-07-09
  • 1970-01-01
  • 2020-09-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多