
本文详解 flask 中 jinja2 模板内 `{{ bg_color }}` 报错的根本原因(变量作用域限制),并提供两种可靠解决方案:修正后的内联样式写法 + 更优雅的纯 css `:nth-child()` 实现。
在 Flask 的 Jinja2 模板中,直接在 {% if %} 块内使用 {% set %} 定义变量(如 bg_color),会导致该变量仅在当前块内有效——这是 Jinja2 的作用域规则(自 2.10+ 版本起严格化)。因此,当您在 if-else 块中设置 bg_color,随后在块外引用 {{ bg_color }} 时,Jinja2 将报 UndefinedError: 'bg_color' is undefined。
✅ 正确做法:将 {% set %} 移至变量实际使用前的同一作用域(即循环体内、
<div style="width: 50%; margin: auto">
{% for comment in comments %}
{% set bg_color = '#e6f9ff' if loop.index % 2 == 0 else '#eee' %}
<div style="padding: 10px; background-color: {{ bg_color }}; margin: 20px">
<p>#{{ loop.index }}</p>
<p style="font-size: 24px">{{ comment }}</p>
</div>
{% endfor %}
</div>⚠️ 注意事项:
- loop.index 从 1 开始计数(非 0),因此 loop.index % 2 == 0 对应偶数项(第 2、4、6… 条),符合需求;
- 避免在 {% if %} 内多次 {% set %},Jinja2 不支持跨分支变量提升;
- 行末 -(如 {% for ... -%})可去除模板生成的多余空白,但非必需。
✨ 更推荐方案:用纯 CSS 实现隔行变色,语义清晰、维护性强、无服务端逻辑耦合:
<div class="comments">
{% for comment in comments %}
<div>
<p>#{{ loop.index }}</p>
<p class="text">{{ comment }}</p>
</div>
{% endfor %}
</div>
<style type="text/css">
.comments {
width: 50%;
margin: auto;
}
.comments > div {
padding: 10px;
background-color: #e6f9ff; /* 默认偶数项背景 */
margin: 20px;
}
.comments > div:nth-child(odd) {
background-color: #eee; /* 奇数项覆盖为灰色 */
}
.comments .text {
font-size: 24px;
}
</style>此方案利用 CSS 的 :nth-child(odd) 伪类精准匹配 DOM 序号(与 Jinja 的 loop.index 一致),无需模板中任何颜色逻辑,且支持响应式、主题切换等进阶场景。对于多数列表渲染需求,CSS 方案是更现代、更健壮的选择。










