如何在Django模板循环中动态访问带索引的字典元素?
解决Django模板中动态拼接字典键名访问值的问题
问题场景
后端views.py中定义了包含200组selectedOptionN和correctAnswerN键值对的detailedStatement字典,并传入result.html模板,代码如下:
# views.py ... detailedStatement = { 'selectedOption1' : '90 degrees', 'correctAnswer1' : '180 degrees', 'selectedOption2' : 'angle', 'correctAnswer2' : 'side' } # 字典实际包含200组键值对 diction = { 'detailedStatement' : detailedStatement } return render(request, "result.html", diction);
期望在HTML表格中渲染为如下格式:
| Sr | Selected Option | Correct Answer |
| 1 | 90 degrees | 180 degrees |
| 2 | angle | side |
但现有模板循环代码无法通过动态拼接键名访问对应值,代码如下:
{% raw %}
{% for dr in detailedResult.items %} <tr> <td>{{forloop.counter}}</td> <td>{{dr.option.forloop.counter}}</td> <td>{{dr.answer.forloop.counter}}</td> </tr> {% endfor %}
{% endraw %}
可行解决方法
方法一:重构后端数据结构(推荐)
将扁平的字典结构改为列表嵌套字典,让数据结构更贴合模板循环的需求,代码维护性更强。
修改views.py中的detailedStatement生成逻辑:
# views.py detailedStatement = [] # 假设你有200组数据,这里用循环生成示例,实际根据你的数据源调整 for i in range(1, 201): # 替换成你实际获取selected和correct值的逻辑 selected_val = '90 degrees' if i == 1 else 'angle' correct_val = '180 degrees' if i == 1 else 'side' detailedStatement.append({ 'selected_option': selected_val, 'correct_answer': correct_val }) diction = { 'detailedStatement': detailedStatement } return render(request, "result.html", diction);
然后在result.html模板中直接循环列表:
{% raw %}
<table> <thead> <tr> <th>Sr</th> <th>Selected Option</th> <th>Correct Answer</th> </tr> </thead> <tbody> {% for item in detailedStatement %} <tr> <td>{{ forloop.counter }}</td> <td>{{ item.selected_option }}</td> <td>{{ item.correct_answer }}</td> </tr> {% endfor %} </tbody> </table>
{% endraw %}
方法二:模板中动态拼接键名(应急方案)
如果无法修改后端代码,可以通过自定义模板过滤器实现动态键名取值:
- 自定义模板过滤器:在你的app目录下创建
templatetags文件夹(需包含__init__.py),新建custom_filters.py文件:
from django import template register = template.Library() @register.filter(name='get_item') def get_item(dictionary, key): return dictionary.get(key, '') # 取不到值时返回空字符串
- 模板中使用过滤器:在
result.html顶部加载过滤器,然后循环生成键名并取值:
{% raw %}
{% load custom_filters %} <table> <thead> <tr> <th>Sr</th> <th>Selected Option</th> <th>Correct Answer</th> </tr> </thead> <tbody> {% for i in "1234567890"|rjust:200 %} {# 生成200次循环 #} {% with counter=forloop.counter %} {% with selected_key='selectedOption'|add:counter|stringformat:"i" correct_key='correctAnswer'|add:counter|stringformat:"i" %} <tr> <td>{{ counter }}</td> <td>{{ detailedStatement|get_item:selected_key }}</td> <td>{{ detailedStatement|get_item:correct_key }}</td> </tr> {% endwith %} {% endwith %} {% endfor %} </tbody> </table>
{% endraw %}
注意:此方法需要依赖自定义过滤器,且循环生成数字的方式较hack,仅作为无法修改后端时的临时方案,优先推荐方法一。
内容的提问来源于stack exchange,提问作者Philip Franklin
相关产品推荐
相关产品推荐

