Аннотирование суммы приводит к None, а не к нулю - PullRequest
45 голосов
/ 28 мая 2011

Я делаю 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)

А вот мой запрос:

answers = Answer.objects.filter(<something here>)
                        .annotate(score=Sum('vote__type'))
                        .order_by('-score')

edit: И чтобы было ясно, я хотел бы сделать это в запросе. Я знаю, что могу превратить его в список, а затем отсортировать в своем коде на Python, но я бы хотел этого избежать, если это возможно.

Ответы [ 2 ]

98 голосов
/ 15 февраля 2016

Вы можете использовать функцию Coalesce из django.db.models.functions, например:

answers = Answer.objects.filter(<something here>)
                        .annotate(score=Coalesce(Sum('vote__type'), 0))
                        .order_by('-score')
0 голосов
/ 28 мая 2011

Как насчет использования пользовательских 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()

Затем вы можете использовать:

>>> answers = Answer.objects.all_with_score().order_by('-score')
...