对Sum进行注释会导致None而不是零

Jac*_*kie 48 django django-models django-orm

我正在创建一个类似于您现在所在页面的QA网站.我试图通过他们的分数来命令答案,但是没有选票的答案将他们的分数设置为无而不是0.这导致答案没有选票在页面底部排在负排名的答案之下.当没有答案投票时,如何使注释得分为零?

这是我的模特:

from django.contrib.auth.models import User

Answer(models.Model):
    //some fields here
    pass

VOTE_CHOICES = ((-1, Down), (1, Up))

Vote(models.Model):
    user = models.ForeignKey(User)
    answer = models.ForeignKey(Answer)
    type = models.IntegerField(choices = VOTE_CHOICES)

    class Meta:
        unique_together = (user, answer)
Run Code Online (Sandbox Code Playgroud)

这是我的查询:

answers = Answer.objects.filter(<something here>)
                        .annotate(score=Sum('vote__type'))
                        .order_by('-score')
Run Code Online (Sandbox Code Playgroud)

编辑:要清楚,我想在查询中执行此操作.我知道我可以把它变成一个列表,然后在我的python代码中对它进行排序,但是如果可能的话我想避免这样做.

小智 111

您可以使用该Coalesce功能django.db.models.functions这样的:

answers = Answer.objects.filter(<something here>)
                        .annotate(score=Coalesce(Sum('vote__type'), 0))
                        .order_by('-score')
Run Code Online (Sandbox Code Playgroud)

  • 具有讽刺意味的是,我猜,这个答案对我来说是最底层的. (2认同)
  • *重要*如果未找到任何行,`coalesce`将返回`null`。不幸的是我必须找到另一个解决方案 (2认同)
  • @EugeneKovalev 什么?不,不是的。 (2认同)

小智 7

来自 django 的Coalesce文档:

防止聚合 Sum() 返回 None。聚合默认参数在底层使用 Coalesce() 。

因此Coalesce,我们可以使用“默认”参数来代替使用 :

answers = Answer.objects.filter(<something here>)
                    .annotate(score=Sum('vote__type', default=0))
                    .order_by('-score')
Run Code Online (Sandbox Code Playgroud)


vas*_*sco -5

那你用自定义的Manager呢?例如:

AnswerManager(models.Manager):
    def all_with_score(self):
       qs = self.get_query_set().annotate(score=Sum('vote__type'))
       # Here, you can do stuff with QuerySet, for example
       # iterate over all Answers and set 'score' to zero if None.

Answer(models.Model):
    //some fields here
    objects = AnswerManager()
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用:

>>> answers = Answer.objects.all_with_score().order_by('-score')
Run Code Online (Sandbox Code Playgroud)

  • 该问题询问如何将内置 Sum 聚合函数的 None 值替换为 0。这不会那样做 (4认同)