Пользовательская функция аннотации 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 один раз в день (или чаще в зависимости от ваших потребностей). И используйте его для ваших нужд (самый горячий список).