【发布时间】:2015-05-08 00:18:09
【问题描述】:
假设我有三个模型:
from django.db import models
class X(models.Model):
y = models.ForeignKey(Y, on_delete=models.PROTECT)
z = models.ForeignKey(Z, on_delete=models.PROTECT)
a = models.DecimalField(...)
b = models.DecimalField(...)
...some fields...
class Y(models.Model):
...some fields...
class Z(models.Model):
...some fields...
我想使用 ORM 使用 X 模型进行聚合查询,但我不想按 X.id 分组(我想按 X.a 分组)并且我希望生成的对象具有 Y和 Z 相关模型预先填充在其中(以避免重复查询相关数据)。
据我所知,Django 的聚合查询只允许您按模型的 ID 分组(在我看来有点没用),或者按另一个字段分组,然后将结果折叠到单个记录/对象中。
没有中间立场允许您按模型 ID 以外的字段进行分组,并且不会将结果折叠到单个记录/对象中。
我意识到这很可能是因为这种中间立场不适合模型的概念(因为如果您将多个模型记录组合在一起,它们真的不再是模型实例了),但如果能够利用 ORM 的力量并达到这个中间立场。
目前我不得不回避 ORM 并推出我自己的自定义模型实现并使用原始查询,但这有点笨拙,我希望随着 Django 1.8 的发布以及我可能能够返回的新查询功能ORM,但似乎并非如此。
我能得到的最接近的是这样的:
X.objects.all().values('a', 'y', 'z').annotate(temp=Sum('b'))
...翻译成这个 SQL:
SELECT app_x.a, app_x.y_id, app_x.z_id, SUM(app_x.b) AS temp
FROM app_x LEFT OUTER JOIN app_y ON (app_x.y_id = app_y.id)
GROUP BY app_x.a, app_x.y_id, app_x.z_id
我想从 ORM 得到的 SQL 是这样的:
SELECT app_x.a, app_y.*, app_z.*, SUM(app_x.b) AS temp
FROM app_x LEFT OUTER JOIN app_y ON (app_x.y_id = app_y.id)
LEFT OUTER JOIN app_z ON (app_x.z_id = app_z.id)
GROUP BY app_x.a, app_y.*, app_z.*
...这样我不仅可以获取相关的 ID,还可以获取完整的模型实例,可以立即使用并避免将来的查询。
ORM 允许这样做吗?
我能看到的唯一解决方案是在 .values() 调用中手动定义相关模型中的所有字段,但这不会返回查询集,而且必须手动列出所有必要的相关信息有点乏味字段(而不是仅仅进行 .select_related() 调用)。
编辑 1
如果 .values() 调用返回实际相关的模型对象而不仅仅是它们的 ID 值,这将很容易。
即我认为这样的查询:
X.objects.all.values('y')
...应该返回包含 Y 个对象而不是 Y 个 ID 的字典列表。
这样的查询:
X.objects.all.values('y_id')
...应该返回包含 ID 的字典列表,因为它是您要求的。
有人同意我的观点吗?
【问题讨论】:
标签: django orm model aggregate-functions