我们有两个型号(简化版):
class Contestant(models.Model):
email = models.EmailField(max_length=255, unique=True)
# plus some other fields
@property
def total_points(self):
return self.points.aggregate(total=Sum('value'))['total'] or 0
class Points(models.Model):
contestant = models.ForeignKey(Contestant, related_name='points')
value = models.PositiveIntegerField()
# plus some other fields which determine based on what we
# awarded ``Points.value``
当我们显示参赛者名单及其total_points
价值时
导致对每个结果进行额外查询 - 即执行以下查询:
total_points
值total_points
值我尝试更改查询集以预取数据,如下所示:
Contestant.objects.filter(...).prefetch_related('points')
...但是,即使它有效,也不会使用预取数据
列出参赛者(因此每个结果仍然会尝试抓取total_points
在单独的查询中。)
是否可以:
Contestant.total_points
@property方法中的预取值)?(我在tastypie
列出结果,如果重要的话。)
谢谢。
答案 0 :(得分:10)
如果您的目标是为每个项目添加汇总值,则应使用annotate
,而不是aggregate
。
例如(一个简单的查询,不需要其他方法):
Contestant.objects.filter(...).annotate(total_points=Sum('points__value'))
如果你真的想把这段代码放在你的查询之外:你可以,但模型方法不是一种正确的方法。模型上的方法用于单个实例上的操作。如果您想在整个QuerySet上执行某些操作,请改用ORM Manager。
使用Manager会看起来像这样:
class TotalPointsManager(models.Manager):
def get_queryset(self):
return super(TotalPointsManager, self).get_queryset().annotate(total_points=Sum('points__value'))
class Contestant(models.Model):
email = models.EmailField(max_length=255, unique=True)
objects = TotalPointsManager() # You are overriding the default manager!
然后你会像往常一样构建你的查询(你可以删除prefetch_related
):
Contestant.objects.filter(...)
... total_points
字段对于每个对象都会“神奇地”可用。