Возвращение словаря из тегов шаблона и печать в шаблоне - PullRequest
0 голосов
/ 10 ноября 2019

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

Печатьодно значение легко, но для более чем одного мне нужно вернуть словарь. Так как я могу вернуть словарь и распечатать все значения в шаблоне.

from django import template
register = template.Library()

    @register.simple_tag
    def getmostvotedanswer(answers):
        answer = answers.order_by('-vote')[0]
        answer_info = {
            'answer':answer.answer,
            'vote':answer.vote,
            'id':answer.id
        }
        return answer_info

index.html

<p class="small text-muted ">{% getmostvotedanswer question.answer_set.all %}</p>
Вывод
{'answer': 'THIS IS ANSWER THIS IS ANSWER THIS IS ANSWER THIS IS ANSWER THIS IS ANSWER', 'vote': 7, 'id': 1}

Я могу вызвать template_tag 3 раза для трех значений.

Но я не хочу вызывать templatetagСнова и снова я думаю, что это повлияет на производительность.

view.py

def index(request):
    questions = Question.objects.all()
    context = {
        'questions':questions
    }
    return render(request,'index.html',context=context)

Правка -> Добавить view.py

1 Ответ

0 голосов
/ 10 ноября 2019

Самый простой, отлаживаемый, лучший в плане производительности и дружественный к тестам способ достижения этого - готовить данные в представлении, а не записывать пользовательский тег шаблона. Для получения первого ответа на каждый вопрос нужны функции Windows:

from django.db.models import F, Window
from django.db.models.functions.window import FirstValue

def index(request):

    #q_and_a_ids = [ (id question, id most voted answer), (... ]
    q_and_a_ids = (
      Question
      .objects
      .annotate(
        most_voted_id=Window(
          expression=FirstValue('answer__id'),
          partition_by=['id'],
          order_by=F('answer__vote').desc()
        )
       )
      .distinct()
      .values_list( 'id', 'most_voted_id')
    )

    answers_ids = set( [ a_id for (_,a_id) in q_and_a_ids] )

    questions_dict = Question.objects.in_bulk()
    answers_dict = Answers.objects.filter(pk__in=answers_ids).in_bulk()

    #q_and_a = [ { 'q':question, 'a':most voted answer}, { ... ]
    q_and_a = [ {'q': questions_dict[q_id],
                 'a': answers_dict.get(a_id) } 
                 for (q_id,a_id) in q_and_a_ids ]

    context = {
        'questions_and_answers': q_and_a
    }
    return render(request,'index.html',context=context)
...