说我有三个型号:
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分组(我想按Xa分组)我希望生成的对象具有Y和Z相关模型预先填充(以避免重复查询相关数据)。
据我所知,Django的聚合查询仅允许您按模型的ID进行分组(在我看来有点无用),或者按其他字段分组,然后将结果折叠为单个记录/对象。 / p>
没有中间地带允许您按照模型ID以外的字段进行分组,而不会将结果折叠为单个记录/对象。
我意识到这很可能是因为这个中间地带不适合模型的概念(因为如果将多个模型记录组合在一起,它们实际上不再是模型实例),但它会很好能够利用ORM的力量并实现这个中间地带。
目前我不得不回避ORM并推出我自己的自定义模型实现并使用原始查询,但它有点hacky我希望发布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的词典列表,因为这是你要求的。
有人同意我的意见吗?
答案 0 :(得分:1)
X.objects.annotate(temp=Sum('b')).select_related('y','z')
是否适合您?
编辑:刚刚看到你在问题中排除了这一点。我没试过,但values_list()
可能会返回外键字段的模型实例吗?如果没有,并且您使用values()
的原因是模型X上的许多不需要的字段,可以考虑使用defer/only