Reputation: 47
I have an app for some quiz with questions and choices. So I'm trying to render all this stuff to Django templates. In my views.py it looks like this
def choice(request):
question_list = get_list_or_404(Question)
page = get_object_or_404(Page, name='about')
letters = ["A", "B", "C", "D", "E"]
return render(request,
'qview/choice.html',
{
'question_list': question_list,
'page': page,
'letters': letters,
}
)
I have a list of questions and list with letters. All of that I'm sending as context to my template.
{% if question_list %}
<ul>
{% for question in question_list %}
<li><a href="#">{{question.question}}</a></li>
<ul>
{% for choice in question.choice_set.all %}
<li>{{ choice.text }}</li>
{% endfor %}
</ul>
{% endfor %}
</ul>
{% else %}
<p>No questions available</p>
{% endif %}
So here I'm going through all of questions and all of choices connected to this question. But I can't get how I can also go through letters list? I was thinking about zip it all. But in view I have only questions not choices, so I can't zip to it.
So what else is possible here?
Upvotes: 0
Views: 799
Reputation: 2303
Django templates make some pretty handy loop builtins available. The one you want to use in this case is forloop.counter0
. Specifically, use it as an index for your letters
list.
A custom template tag will help with making this more readable:
Create a custom template tag in templatetags/index.py
:
from django import template
register = template.Library()
@register.filter
def index(indexable, i):
return indexable[I]
Import the custom template tag at the top of your django template:
{% load index %}
Use the index
tag inside your template to access the counter0
loop variable:
{% if question_list %}
<ul>
{% for question in question_list %}
<li><a href="#">{{question.question}}</a></li>
<ul>
{% for choice in question.choice_set.all %}
<li>{{ letters|index:forloop.counter0 }}: {{ choice.text }}</li>
{% endfor %}
</ul>
{% endfor %}
</ul>
{% else %}
<p>No questions available</p>
{% endif %}
Suggestion, it might be a better idea to "zip" them together and pass the zipped output to the template (you were already thinking about this -- good!) Templates should know as little as possible about your business logic and make as few assumptions as possible about your data structures.
Upvotes: 2
Reputation: 9859
So it'll be like A choice01, B choice 02 and so on
This can be solved by HTML. Use an ordered list.
<ol type="A">
{% for choice in question.choice_set.all %}
<li>{{ choice.text }}</li>
{% endfor %}
</ol>
The above will produce a list like
A. choice 01
B. choice 02
...
Notice the dot (.
) after the letter label/prefix. You could probably get rid of the dot with some CSS styling if it's considered not desirable.
Upvotes: 1
Reputation: 6378
cycle
tag is perfect for such manner. It goes in for loop and takes first argument for first iteration, second for second and so on... If they are not enough, then it starts from the begininng.
{% for choice in question.choice_set.all %}
<li>{% cycle 'A' 'B' 'C' 'D' 'E' 'F' %}: {{ choice.text }}</li>
{% endfor %}
Upvotes: 0