Django模板遍历字典等长列表按索引分组展示为空问题求助
问题原因
你的代码无法正常渲染是两个写法错误导致的:
- 直接遍历字典
weather时,循环变量拿到的是字典的键名(即'temp'、'time'、'pop'三个字符串),并非你预期的列表索引值。 - Django模板的点语法不支持动态解析变量作为属性/索引名,你写的
{{weather.temp.x}}会让模板引擎尝试查找temp列表上名为x的固定属性/键,不会把x替换为循环变量的实际值,自然取不到对应数据,只能渲染空行。
解决方案
方案1(推荐,符合Django开发规范)
模板层只负责渲染逻辑,数据结构转换放在视图层处理是最优选择。你可以在视图中用zip把三个平行列表打包为按组聚合的元组列表,再传给模板,模板直接遍历即可,不需要写复杂的取值逻辑。
视图层调整示例:
# 原有三个列表temp、time、pop保持不变 weather = { 'temp' : temp, 'time' : time, 'pop' : pop } # 新增分组后的列表,加入上下文传给模板 weather_groups = list(zip(temp, time, pop)) context = { 'weather': weather, 'weather_groups': weather_groups }
模板层代码:
{% for group_temp, group_time, group_pop in weather_groups %} <p> <span>{{ group_temp }}</span> <br> <span>{{ group_pop }}</span> <br> <span>{{ group_time }}</span> <br> </p> {% endfor %}
这个写法逻辑清晰,没有模板层hack,后续维护成本最低。
方案2(不修改视图传参的兼容写法)
如果你暂时不想调整视图代码,可以自定义一个简单的索引取值模板过滤器,实现动态按索引取列表值的效果。
首先在你对应app的templatetags目录下新建custom_filters.py(如果目录不存在就手动创建,别忘了在目录下加空的__init__.py文件标识为Python包),写入以下代码:
from django import template register = template.Library() @register.filter def get_index(lst, idx): try: return lst[idx] except (IndexError, TypeError): return ""
模板顶部先加载自定义过滤器:
{% load custom_filters %}
之后循环逻辑就可以正常按索引取值了:
{% for item in weather.temp %} <p> <span>{{ item }}</span> <br> <span>{{ weather.pop|get_index:forloop.counter0 }}</span> <br> <span>{{ weather.time|get_index:forloop.counter0 }}</span> <br> </p> {% endfor %}
这里forloop.counter0是Django模板for循环自带的变量,值为从0开始的当前循环索引,和三个列表的下标完全对应。
注意:不要尝试直接用
weather.temp.forloop.counter0这类写法取值,Django模板的点语法查找顺序是字典键>对象属性>数字索引,这种写法会被引擎解析为查找temp字典下forloop键对应的counter0属性,完全拿不到你要的索引值。
内容的提问来源于stack exchange,提问作者karan randhawa
相关产品推荐
相关产品推荐

