Django 1.9 中的 query.group_by
Posted
技术标签:
【中文标题】Django 1.9 中的 query.group_by【英文标题】:query.group_by in Django 1.9 【发布时间】:2016-06-04 03:27:00 【问题描述】:我正在将代码从 Django 1.6 移动到 1.9。 在 1.6 中我有这个代码
models.py
class MyReport(models.Model):
group_id = models.PositiveIntegerField(blank=False, null=False)
views.py
query = MyReport.objects.filter(owner=request.user).query
query.group_by = ['group_id']
entries = QuerySet(query=query, model=MyReport)
查询将为每个 'group_id' 返回 一个 对象;由于我使用它的方式,任何带有 group_id 的表行都可以作为代表。
在 1.9 中,此代码已损坏。上面第二行之后的查询是:
SELECT "reports_myreport"."group_id", ... etc FROM "reports_myreport" WHERE "reports_myreport"."owner_id" = 1 GROUP BY "reports_myreport"."group_id", "reports_report"."otherfield", ...
基本上它列出了group by子句中的所有表字段,使查询返回整个表。
尽管我在调试器中看到
query.group_by = ['group_by']
看起来 query.group_by 不是 1.9 中的方法,1.7-1.9 的更改日志也没有表明发生了某些变化。
有没有更好的方法——不依赖于内部 Django 的东西——我可以用于我的查询?
有什么方法可以修复我当前的查询吗?
【问题讨论】:
group_id
与您的MyReport
有什么关系?您能否向您的模型展示相关部分?
@Sayse `group_id' 是模式中的一个简单字段。我用相关行编辑了问题
啊,好吧,我原以为它是一个外键……你在找MyReport.objects.filter(owner=request.user).distinct('group_id')
吗?
@Sayse 目前我没有使用 Postgres,所以我不确定 100%。 distinct(field) 返回表行还是仅返回不同的字段?我总是可以做类似的事情,但这似乎不是正确的解决方案:`objs = MyReport.objects.filter(owner=request.user).values_list('group_id', flat=True).distinct() for o in对象:MyReport.objects.filter(owner=request.user, group_id=o)[0] `
它返回不同的对象是的。所以完整的模型
【参考方案1】:
您可以使用order_by() 来获取排序的结果,在同一个查询中,您可以按第二个条件排序。
如果您想获取组,则需要遍历集合以检索这些值。
如果你消费了查询返回的所有结果,你可以考虑:
a) itertools.groupby 改为在内存中分组,但您不应该将它用于大型数据集。
b) 另一种选择是使用Manager.raw(),但您需要在 Django 中编写 SQL,如下所示:
for report in MyReport.objects.raw('SELECT * FROM reporting_report GROUP by group_id'):
print(report)
这适用于大型数据集,但您可能会失去与某些数据库引擎的兼容性。
奖励:我建议您在重写之前了解旧代码的确切作用。
【讨论】:
旧代码会为每个 group_id 返回一个条目(完整的表格行)。我不知道它是否错误地工作并且现在按设计工作。您的两种解决方案都应该有效,但是正如您自己提到的那样,它们都会遇到问题。我在上面的评论中的解决方案(无法让code
工作)也有效,但我查询的组数远非理想......
显然,旧代码错误地工作了。在没有聚合的情况下进行 group_by 并没有真正定义。上面的建议(以及我在之前的评论中的建议)有效。在 Postgres 中,这可以更简单地完成。以上是关于Django 1.9 中的 query.group_by的主要内容,如果未能解决你的问题,请参考以下文章
django 1.9 中的 from django.views.generic.simple import direct_to_template 相当于啥