【问题标题】:A QuerySet by aggregate field valueA QuerySet 按聚合字段值
【发布时间】:2010-10-03 07:48:15
【问题描述】:

假设我有以下模型:

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' 不是可用于查询的数据库字段。

【问题讨论】:

    标签: python django database


    【解决方案1】:

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

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

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

    【讨论】:

    • 是的,你可以。您只需将总和作为查询的一部分。
    • 'RelatedManager' 对象没有属性 'sort' :(
    • @okoman... 这意味着您没有使用 list() 函数转换为列表
    • 我不知道为什么这被否决了。碰巧在这种情况下,您可以通过聚合查询中的某个列来进行排序,但通常如果您有更复杂的东西,您就是 SOL。这个解决方案效果很好,虽然它很贵......
    【解决方案2】:

    db级order_by无法通过模型的python方法对查询集进行排序。

    解决方案是将score 字段引入Image 模型,并在每次Vote 更新时重新计算它。某种非规范化。什么时候可以按它排序。

    【讨论】:

    • 我不确定这是最好的解决方案,但它是一个解决方案。
    【解决方案3】:

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

    所以查询可能如下所示:

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

    【讨论】:

    • 我得到的结果是乱序的......它们大多是有序的,但其中一些放错了位置......这可能是什么原因?
    • 这只是针对特定情况的解决方案,不适用于问题标题:“QuerySet order by method”。这不是按方法订购查询集的解决方案:@S.Lott 响应是通用案例的正确解决方案
    猜你喜欢
    • 2022-01-14
    • 2021-10-13
    • 2011-03-26
    • 1970-01-01
    • 2019-11-08
    • 2014-10-19
    • 1970-01-01
    • 2010-12-20
    • 1970-01-01
    相关资源
    最近更新 更多