Пользовательская функция аннотации Django

Я хочу создать простой список горячих вопросов, используя Django. У меня есть функция которая оценивает " горячность" каждого вопроса, основываясь на некоторых аргументах.

Функция выглядит примерно так (полная функция здесь)

def hot(ups, downs, date):
    # Do something here..
    return hotness

Мои модели для моделей вопросов и голосования (соответствующая часть)

class Question(models.Model):
    title = models.CharField(max_length=150)
    body = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

class Vote(models.Model):
    question = models.ForeignKey(Question, related_name='questions_votes')
    delta = models.IntegerField(default=0)

Теперь delta attribute является либо положительным, либо отрицательным. Горячая функция получает количество положительных голосов и количество отрицательных голосов и дату создания вопроса.

Я пробовал что-то вроде этого, но он не работает.

 questions = Question.objects.annotate(hotness=hot(question_votes.filter(delta, > 0),question_votes.filter(delta < 0), 'created_at')).order_by('hotness')

Ошибка, которую я получаю: global name 'question_votes' is not defined
Я понимаю ошибку, но я не делаю этого правильно.

Ответ 1

Вы не можете использовать функции python для аннотаций. Аннотация - это вычисление, которое выполняется на уровне базы данных. Django предоставляет вам только набор базовых вычислений, которые могут обрабатываться базой данных - SUM, AVERAGE, MIN, MAX и т.д. Для более сложных продуктов только с версии 1.8 у нас есть API для более сложных выражения запроса. До Django 1.8 единственным способом достижения аналогичной функциональности было использование .extra, что означает запись простого SQL.

Итак, у вас в основном есть два с половиной варианта.

Первые с половиной.

Напишите вычисление вашей горячности в простом SQL с помощью .extra или через новый API, если ваша версия Django равнa > 1.8.

Второй.

Создайте поле жара внутри модели, которое будет вычисляться заданием cron один раз в день (или чаще в зависимости от ваших потребностей). И используйте его для ваших нужд (самый горячий список).