Django:按组分组?

4
我正在寻找类似以下内容的东西:
previous_invoices = Invoice.objects.filter(is_open=False)
                                   .order_by('-created')
                                   .group_by('user')

但是group_by()不存在...

这将为每个用户找到最近关闭的发票。

这个聚合API似乎可以让你对计数和求和等进行操作,但我不需要计数或求和,我实际上想要发票对象!


当使用group by时,selected的东西是否已定义?我会期望它会根据SQL实现而产生不同的结果... - user3012759
@user3012759 不行。排序发生在分组之后,你在该组中获得哪个记录是未定义的。我花了一段时间才真正理解这一点。ONLY_FULL_GROUP_BY 应该默认启用,以避免犯这种错误。 - mpen
嘿@mpen,我添加了一个更近期的回答尝试。愿意看一下吗? - John Moutafis
@JohnMoutafis 当然可以看一下。虽然我不再使用Django,但如果我使用的话,那看起来会很有帮助 :-) - mpen
很高兴知道 @mpen :) - John Moutafis
2个回答

2

有一个来自2007年的页面将其Hack到了Django上,但是这将毫无意义,因为1.1之前的版本中已经有未记录的Group_by语句。不过一年前的这个帖子似乎有些见解。基本上:

Django有意地没有在ORM中暴露"GROUP BY"或类似的内容。虽然我们有时会发现它是通过关系型后端存储泄漏出来的,但ORM API相当SQL-agnostic。相反,我们公开特定的功能块,当它被转换成SQL时就使用"GROUP BY"来实现(也可能由一组完全不同的神奇精灵来实现,拥有不同的存储系统后端)。

还可以查看有关使用extra的提及,以及可能失败的神奇方式。祝好运。


2

选项1:

虽然在Django中不存在group_by(),但您可以尝试通过利用latest()方法并过滤用户来解决检索每个用户的最近关闭发票的问题:

previous_invoices = Invoice.objects.filter(user=my_user, is_open=False)
                                   .latest('created') 

对于旧版本的Django,不存在latest()方法,查询语句将如下所示:

previous_invoices = Invoice.objects.filter(user=my_user, is_open=False)
                                   .order_by('-created')[0]

选项2:

更新:我后来在这里添加了一个问答样式的示例:如何在Django ORM中执行GROUP BY ... COUNT或SUM?,展示了如何在Django ORM上模拟GROUP BY操作。

如果您绝对想要创建group_by的效果,那么您可以按照此处接受的答案手动创建一个,如Django GROUP BY field value所示。

  1. Use .values_list() with flat=True to get a list of the existent values in your database (if you don't know them beforehand). Also use .distinct() to eliminate duplicate values as we do not care for those:

    value_list = MyModel.objects.values_list(
        'interesting_field', flat=True
    ).distinct()
    
  2. Now iterate through value_list and fill your dictionary:

    group_by_value = {}
    for value in value_list:
        group_by_value[value] = MyModel.objects.filter(interesting_field=value)
    

Now group_by_value dictionary contains as keys the distinct values in your interesting_field and as values the queryset objects, each containing the entries of MyModel with interesting_field=a value from value_list.


注意:

有一个名为django-group-by的库,声称可以在Django中添加group_by()函数,你可能想要查看一下。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接