我想使用Django ORM過濾註釋。很多我在這裏發現的,因此文章都是相當過時,在1.2至1.4天針對Django的背:過濾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
(與所有的字段),與Max(entry_date)
和沿Min(entry_date)
,對於每個關聯的Milestone
,但僅限那些Milestone
記錄,其關聯的Milestone_meta
標記的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真的應該被使用的情況。 – e4c5
文檔指出'extra'最終會被棄用。理想情況下,我希望在某種程度上使用一些未來可行的產品。 –
那麼使用更強大,甚至更好的原始sql – e4c5