Запуск аннотирования или объединения для связанных объектов и рендеринга в шаблоне?

#django

#django

Вопрос:

Я пытаюсь выполнить математику / найти max / avg и т.д. В своих представлениях, а затем отобразить их в шаблоне, но, похоже, я не могу понять, как заставить все это работать. Вычисления должны выполняться над связанными объектами, и я чувствую, что перепробовал все. У меня в голове не укладывается.

views.py

 def program_detail_view(request, primary_key):
    survey = Survey.objects.get(pk=primary_key)
    maxResp = survey.objects.annotate(max_resp=Max('responseRelevance'))
    context = {'survey' : survey, 'maxResp': maxResp}
    return render(request, 'relevance/programStats.html', context=context)
  

models.py

 class Survey(models.Model):
    ...
class Choice(models.Model):
    survey = models.ForeignKey(Survey, on_delete=models.CASCADE)
    creationDate = models.DateTimeField(auto_now_add=True)
    pce = models.IntegerField(
        validators=[MaxValueValidator(4),
        MinValueValidator(1)], choices=radioChoices,
        )
    interest = models.IntegerField(
        validators=[MaxValueValidator(4),
        MinValueValidator(1)], choices=radioChoices,
        )
    responseRelevance = models.IntegerField(blank=True)
  

template.html

     <li>Overall Relevance Score: {{ maxResp }}</li>

  

Я ожидаю, что представления выдадут максимальный отклик из набора вариантов, но вместо этого в шаблоне ничего не отображается, независимо от того, как я пытаюсь его вызвать. Я пробовал то же самое для average и других функций аннотирования / агрегирования.

Комментарии:

1. Забыл добавить, что да, я использую {% block content %} и {% endblock %} и такие вещи, как {{ survey.choice_set.all.count }} рендеринг в шаблоне.

2. Для одного опроса это должно быть .aggregate(..) и .aggregate(..) вернет словарь всех агрегатов, поэтому здесь словарь будет содержать один элемент: 'max_resp' .

Ответ №1:

Вы можете либо агрегировать по данному Survey объекту, либо аннотировать объект вашего опроса, который вы извлекаете в первом запросе. Последнее приводит только к одному запросу к базе данных и, таким образом, вероятно, немного более эффективно.

Таким образом, мы можем .annotate(..) наш Survey объектный запрос, и в качестве аннотации мы используем Max('choice__responseRelevance') , поскольку мы хотим получить максимум responseRelevance по всем связанным вариантам:

 def program_detail_view(request, primary_key):
    survey = Survey.objects.annotate(
        max_resp=Max('choice__responseRelevance')
    ).get(pk=primary_key)
    context = {'survey' : survey}
    return render(request, 'relevance/programStats.html', context=context)  

теперь мы можем отобразить это аннотированное значение с:

 <li>Overall Relevance Score: {{ survey.max_resp }}</li>  

Комментарии:

1. Это имеет смысл! Хотя по какой-то причине он по-прежнему не хочет отображаться на странице на сервере разработки. Там, где {{ survey.max_resp }} должно быть указано число, оно пустое.

2. @holmesian17: есть ли какие-нибудь связанные Choice с? Так как если их нет, то результат таков None .

3. Похоже, что есть 5 связанных Choice файлов, которые отображаются при добавлении {{ survey.choice_set.all.count }} (кстати, спасибо за вашу помощь — это заставило меня рвать на себе волосы.)

4. @holmesian17: а responseRelevance ов выбора нет NULL ? Есть ли какая -то конкретная причина, по которой вы их устанавливаете blank=True ?

5. Они не равны нулю. Я начинаю понимать, что я оставил пару, возможно, важных вещей вне моего вопроса. Я установил его как, blank=True потому что под responseRelevance вычисляется, когда форма отправляется двумя другими числами. def calculate(self): responseRelevance = ((self.pce * self.pce)*self.interest) return responseRelevance и затем он сохраняет его в responseRelevance