如何用Django模板标签正确渲染学生测试题及对应选项?
问题:Django模板渲染试题与选项错误修正
场景与数据结构
基于Django开发学生知识水平评估测试网站,需要实现试题及对应选项的正确渲染。当前数据存储结构如下:
questions = ["question1", "question2", "question3"] answers = [ ["answer1", "answer2", "answer3"], ["answer1", "answer2", "answer3", "answer4"], ["answer1", "answer2", "answer3"] ]
期望渲染效果
期望渲染后呈现如下格式(带单选按钮):
question1 [单选按钮] answer1 [单选按钮] answer2 [单选按钮] answer3 question2 [单选按钮] answer1 [单选按钮] answer2 [单选按钮] answer3 [单选按钮] answer4 question3 [单选按钮] answer1 [单选按钮] answer2 [单选按钮] answer3
当前错误模板代码
当前模板代码无法正确匹配试题与对应选项,会在每道题下渲染所有选项组:
{% for question in questions %} <p>{{question}}</p> <ul> {% for answer in answers %} {% for current in answer %} <li><input type="radio" id="option{{ forloop.parentloop.counter }}_{{ forloop.counter }}" name="answer{{ forloop.parentloop.counter }}" value="{{ current }}">{{ current }}</li> {% endfor %} {% endfor %} </ul> {% endfor %}
修正方案
方案一:视图层打包试题与选项(推荐)
提前在视图中将试题和对应选项打包成元组列表,避免模板层复杂索引操作:
视图代码:
def test_view(request): questions = ["question1", "question2", "question3"] answers = [ ["answer1", "answer2", "answer3"], ["answer1", "answer2", "answer3", "answer4"], ["answer1", "answer2", "answer3"] ] # 打包为(问题, 对应选项列表)的元组集合 question_option_pairs = zip(questions, answers) return render(request, 'test_template.html', {'question_pairs': question_option_pairs})
模板代码:
{% for question, options in question_pairs %} <p>{{ question }}</p> <ul> {% for option in options %} <li> <input type="radio" id="option{{ forloop.parentloop.counter }}_{{ forloop.counter }}" name="answer{{ forloop.parentloop.counter }}" value="{{ option }}"> {{ option }} </li> {% endfor %} </ul> {% endfor %}
方案二:自定义模板过滤器实现索引取值
如果不想修改视图逻辑,可以通过自定义过滤器实现模板中按索引取对应选项:
- 在Django app下创建
templatetags目录,添加__init__.py和custom_filters.py文件 - 在
custom_filters.py中编写过滤器:
from django import template register = template.Library() @register.filter def get_item(lst, index): try: return lst[index] except IndexError: return None
- 模板中加载过滤器并使用:
{% load custom_filters %} {% for question in questions %} <p>{{ question }}</p> <ul> {% for option in answers|get_item:forloop.counter0 %} <li> <input type="radio" id="option{{ forloop.parentloop.counter }}_{{ forloop.counter }}" name="answer{{ forloop.parentloop.counter }}" value="{{ option }}"> {{ option }} </li> {% endfor %} </ul> {% endfor %}
内容的提问来源于stack exchange,提问作者Oleh
相关产品推荐
相关产品推荐

