我有这样的模特:
class PledgeItem(models.Model):
title = models.CharField(...)
usd_amount = models.DecimalField(...)
class Pledger(models.Model):
name = models.CharField(...)
...
class Pledge(models.Model):
pledger = models.ForeignKey(Pledger)
item = models.ForeignKey(PledgeItem)
usd_amount = models.DecimalField(...)
...
我的PledgeItem
有一种方法可以确定承诺的百分比(例如,一项可能需要花费100美元,并且每项承诺为20美元,这意味着它已承诺60%):
class PledgeItem(models.Model):
...
def percentage_pledged(self):
pledge_total = Pledge.objects.filter(item = self).sum(usd_amount)
return (pledge_total / self.usd_amount) * 100
出于这个问题的目的,请假设我正确处理self.usd_amount
为零,以及Pledges
上没有PledgeItem
的情况(尽管我不得不问,为什么sum(field)
在这些情况下会返回None
?)。
问题是,如果我在percentage_pledged
n
列表中拨打PledgeItems
,则每个PledgeItem
都会有一个查询。有没有一种优雅的解决方法,而不使用save
信号来更新percentage_pledged
字段?如果我能以某种方式预取这些数据(即一次获取所有Pledges
,然后循环遍历它们),那就太好了。
我不确定解决方案看起来会是什么样的(例如,那套Pledges
会在哪里生活?),但我确信这是一个常见的问题(而且这个问题一直困扰着我之前),所以我想我会看到人们对Django更有经验的解决方案。也许save
信号是它所属的地方,特别是对于“低写,高读”类型的站点。
答案 0 :(得分:3)
这是Django 1.1中新聚合功能的工作。
您希望将“pledge_sum”字段“注释”到查询集中的每个PledgeItem。这很容易做到:
from django.db.models import Sum
PledgeItems.objects.all().annotate(pledge_sum=Sum(pledge__usdamount))
显然,您可以使用您想要的任何过滤器替换all()
。
您仍然需要对每个PledgeItem进行百分比计算,但不会产生任何额外的查询。