
jinja2 模板中 `{% set %}` 声明的变量在 for 循环内无法真正“更新”,因其作用域为当前渲染上下文,每次 `{% set %}` 实际创建的是新局部变量。正确做法是直接基于循环索引(如 `loop.index0` 或 `range`)动态计算值。
在 Flask 的 Jinja2 模板中,{% set x_value_weeks = ... %} 语句看似可赋值,但 Jinja2 的变量绑定是不可变作用域(immutable scoping):在 for 循环内部使用 {% set %} 并不会修改外层同名变量,而是为该次迭代创建一个独立的、仅在当前块内有效的局部副本。因此,你观察到 x_value_weeks 始终保持初始值(如 5),后续的 {% set x_value_weeks = x_value_weeks + 10 %} 并未实现预期的累加效果。
✅ 正确且推荐的解决方案是避免状态维护,改用纯函数式表达式——利用循环变量或内置 loop 对象动态计算坐标:
✅ 推荐写法(基于 loop.index0)
? loop.index0 从 0 开始计数(第1次迭代为0,第2次为1…),因此 base_x + loop.index0 * step 精确生成 5, 15, 25, ... 序列。
✅ 替代写法(显式 range,适用于无数据源场景)
{% for i in range(weeks|length) %} {% endfor %}
⚠️ 注意事项
- ❌ 不要依赖 {% set %} 在循环中“更新”变量——这是 Jinja2 的设计限制,非 bug;
- ✅ 优先使用 loop.index, loop.index0, loop.revindex 等内置属性,语义清晰且高效;
- ✅ 若需复用复杂计算逻辑,可提前在 Flask 视图中预处理(例如生成带 x_pos 属性的 week_items 列表),再传入模板,提升可读性与性能;
- ? 所有 x 值最终输出为字符串,确保单位(如 px)无需额外添加(SVG 的 x 属性默认单位为用户坐标,纯数字即可)。
通过消除模板中的状态依赖,代码更符合 Jinja2 的声明式范式,也更易测试、调试和维护。










