代码之家  ›  专栏  ›  技术社区  ›  okoman

按聚合字段值设置的查询集

  •  27
  • okoman  · 技术社区  · 17 年前

    假设我有以下模型:

    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' )
    

    就像我担心的那样 'score' 不是可以在查询中使用的数据库字段。

    3 回复  |  直到 7 年前
        1
  •  47
  •   Alex Koshelev    17 年前

    哦,当然,我忘记了Django和它的新的聚合支持 annotate 功能。

    因此查询可能如下所示:

    Contest.objects.get(pk=id).image_set.annotate(score=Sum('vote__value')).order_by( 'score' )
    
        2
  •  9
  •   S.Lott    17 年前

    您可以非常简单地用Python编写自己的类型。

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

    这很好地工作,因为我们对列表进行了排序,我们将提供给模板。

        3
  •  2
  •   Alex Koshelev    17 年前

    数据库级 order_by 无法按模型的python方法对queryset排序。

    解决办法是介绍 score 字段到 Image 建模并在每个 Vote 更新。某种非规范化。你什么时候可以按它排序。