【发布时间】:2015-12-09 23:12:27
【问题描述】:
我想使用 Django ORM 过滤注释。我在 SO 上找到的很多文章都过时了,目标是 1.2 到 1.4 天内的 Django:
-
Filtering only on Annotations in Django - 2010 年的这个问题建议使用
extra子句,官方 Django 文档不建议这样做 - Django annotation with nested filter - 从 2011 年开始,此问题中提供了类似的建议。
Django 1.8 添加了conditional aggregation,这似乎是我想要的,但我不能完全弄清楚我最终需要的语法。这是我的模型和我试图达到的场景(为简洁起见,我简化了模型):
class Project(models.Model):
name = models.CharField()
... snip ...
class Milestone_meta(models.Model):
name = models.CharField()
is_cycle = models.BooleanField()
class Milestone(models.Model):
project = models.ForeignKey('Project')
meta = models.ForeignKey('Milestone_meta')
entry_date = models.DateField()
我想获取每个 Project(及其所有字段),以及每个关联 Milestone 的 Max(entry_date) 和 Min(entry_date),但仅适用于关联 Milestone_meta 的那些 Milestone 记录is_cycle 标志设置为 True。换句话说:
- 对于每个项目记录,给我最大和最小里程碑 entry_dates,但仅当关联的 Milestone_meta 的给定标志设置为 True 时。
目前,我正在获取项目列表,然后在循环中获取 Max 和 Min 里程碑,导致 N+1 数据库命中(如您所料,这会变慢):
pqs = Projects.objects.all()
for p in pqs:
(theMin, theMax) = getMilestoneBounds(p)
# Use values from p and theMin and theMax
...
def getMilestoneBounds(pid):
mqs = Milestone.objects.filter(meta__is_cycle=True)
theData = mqs.aggregate(min_entry=Min('entry_date'),max_entry=Max('entry_date'))
return (theData['min_entry'], theData['max_entry'])
如何将其减少到一两个查询?
【问题讨论】:
-
我认为这绝对是真正应该使用额外甚至原始 sql 的情况。
-
文档表明
extra最终将被弃用。理想情况下,我想在某种程度上使用一些面向未来的东西。 -
那么使用更强大甚至更好的原始sql
标签: django django-models orm