
在django模板中无法直接通过list.{{week.number}}.0等方式动态索引嵌套列表,需借助自定义模板过滤器实现安全、可读的动态访问。
Django模板语言(DTL)本身不支持动态变量作为列表或嵌套结构的索引(例如 activity_list.{{ week.number }}.0),因为点号(.)访问符仅支持静态属性名或整数下标字面量(如 .0、.1),不支持表达式求值。当您尝试使用 activity_list.week.number.0 时,Django 会将其解析为字面属性链(即查找名为 "week" 的属性,再找其 "number" 属性),而非将 week.number 的值(如 2)作为索引代入。
✅ 正确解法:编写轻量级自定义模板过滤器
在您的应用目录下(如 myapp/templatetags/list_extras.py),创建如下过滤器:
# myapp/templatetags/list_extras.py
from django import template
register = template.Library()
@register.filter
def get_item(container, key):
"""
安全获取容器中指定键/索引的值。
支持 list[int], dict[key], 以及带 __getitem__ 的对象。
"""
try:
return container[key]
except (KeyError, TypeError, IndexError):
return None⚠️ 别忘了在模板顶部加载该标签库:
{% load list_extras %}✅ 模板中使用示例(假设 week 是 Plan 对象的一个属性或循环变量,且 week.number 返回整数 0–N):
{% for week in plan.weeks_range %} {# 假设您在视图中传入了 range(weeks) 或类似结构 #}
Week {{ week }}
{% with monday_activity=activity_list|get_item:week|get_item:0 %}
{% if monday_activity %}
Monday: {{ monday_activity.name }} ({{ monday_activity.distance }} km)
{% else %}
Monday: No activity
{% endif %}
{% endwith %}
{% endfor %}? 关键说明:
- 过滤器链 |get_item:week|get_item:0 等价于 Python 中的 activity_list[week][0];
- 使用 {% with %} 提升可读性与复用性,避免重复调用;
- 过滤器内置异常捕获,防止模板崩溃,返回 None(可配合 |default:"–" 处理空值);
- 切勿在视图中“预展开”所有数据(如构建含完整活动结构的字典),这会破坏关注点分离;保持逻辑在后端、展示在模板,而动态索引由过滤器桥接。
? 进阶建议:若频繁操作此类嵌套结构,可在视图中将 activity_list 封装为支持属性访问的类(如 WeekActivities),但对简单场景,自定义过滤器是最简洁、符合 Django 设计哲学的方案。










