2009-01-24 39 views
26

比方说,我有以下型号:订购一个QuerySet通过聚合字段值

class Contest: 
    title = models.CharField(max_length = 200) 
    description = models.TextField() 

class Image: 
    title = models.CharField(max_length = 200) 
    description = models.TextField() 
    contest = models.ForeignKey(Contest) 
    user = models.ForeignKey(User) 

    def score(self): 
     return self.vote_set.all().aggregate(models.Sum('value'))[ 'value__sum' ] 

class Vote: 
    value = models.SmallIntegerField() 
    user = models.ForeignKey(User) 
    image = models.ForeignKey(Image) 

一个网站的用户可以贡献自己的图像数竞赛。然后其他用户可以向上或向下投票。 一切工作正常,但现在我想显示一个页面,用户可以在其中看到某个比赛的所有贡献。图像应按其得分排序。 所以我尝试了以下内容:

Contest.objects.get(pk = id).image_set.order_by('score') 

正如我担心这是行不通的,因为“成绩”是一个可以在查询中使用任何数据库字段。

回答

47

哦,当然,我忘记了Django中的新聚合支持及其annotate功能。

所以查询可能是这样的:

Contest.objects.get(pk=id).image_set.annotate(score=Sum('vote__value')).order_by('score') 
9

你可以用Python编写你自己的排序方式。

def getScore(anObject): 
    return anObject.score() 
objects= list(Contest.objects.get(pk = id).image_set) 
objects.sort(key=getScore) 

这很好用,因为我们对我们要提供给模板的列表排序。

+0

是的,可以。您只需将总和作为查询的一部分。 – 2009-01-24 13:36:12

+0

'RelatedManager'对象没有属性'排序' :( – okoman 2009-01-24 13:45:08

+2

@okoman ...这意味着你没有使用list()函数转换为列表 – Jiaaro 2009-07-16 14:47:48

1

db级别order_by无法按模型的python方法对queryset进行排序。

解决的办法是将score字段引入Image模型,并在每更新Vote时重新计算它。某种反规范化。当你可以按它排序。