
在 Flask 模板中向 Chart.js 传递标签(labels)时,直接使用 {{ labels }} 会导致 HTML 实体转义错误(如 &),应改用 Jinja2 的 | tojson 过滤器安全序列化 Python 数据为合法 JavaScript 对象。
在 flask 模板中向 chart.js 传递标签(labels)时,直接使用 `{{ labels }}` 会导致 html 实体转义错误(如 `&`),应改用 jinja2 的 `| tojson` 过滤器安全序列化 python 数据为合法 javascript 对象。
在 Chart.js(尤其是 v4+)中,labels 并非某个 dataset 的属性,而是属于顶层 data 对象的全局配置项——它为所有数据集提供横轴(x 轴)或类别索引的语义标识。因此,将 labels 错误地写在某个 dataset 内(如 datasets[3].labels)不仅无效,还会因 Jinja2 模板未正确转义而引发 Uncaught SyntaxError: Unexpected token '&' 等解析错误。
该错误的根本原因在于:Flask/Jinja2 默认会对变量输出进行 HTML 转义。当 Python 列表 ['test1', 'test2', 'test3'] 经 {{ labels }} 渲染时,引号可能被转义为 ",而 & 字符在 JS 上下文中非法,导致浏览器解析失败。
✅ 正确做法是:
- 将 labels 提升至 data 顶层(符合 Chart.js 官方数据结构);
- 使用 | tojson 过滤器——它会自动处理引号、转义和类型转换,输出标准 JSON 格式(如 ["test1","test2","test3"]),可直接被 JavaScript 解析;
- 确保 data 数组中的每个点对象包含 x 和 y 属性(散点图必需)。
以下是修正后的完整示例代码:
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.3/dist/chart.umd.min.js"></script>
<script>
// ✅ 正确:labels 在 data 顶层,且经 tojson 安全序列化
const chartData = {
labels: {{ labels | tojson }}, // → ["test1", "test2", "test3"]
datasets: [
{
type: 'line',
label: 'Trend Line',
data: {{ line_data | tojson }},
backgroundColor: 'rgba(168, 38, 8, 0.1)',
borderColor: 'rgb(168, 38, 8)',
borderWidth: 3,
pointRadius: 0,
order: 2
},
{
type: 'scatter',
label: 'Group A',
data: {{ scatter_data_a | tojson }},
backgroundColor: 'rgb(168, 38, 8)',
borderColor: 'rgb(168, 38, 8)',
pointRadius: 3,
order: 3
},
{
type: 'scatter',
label: 'Group B',
data: {{ scatter_data_b | tojson }},
backgroundColor: 'rgb(46, 179, 84)',
borderColor: 'rgb(46, 179, 84)',
pointRadius: 3,
order: 1
}
]
};
const config = {
type: 'scatter',
data: chartData,
options: {
maintainAspectRatio: true,
aspectRatio: 1,
plugins: {
legend: { display: true },
tooltip: {
callbacks: {
label: (context) => `${context.dataset.label}: (${context.parsed.x.toFixed(2)}, ${context.parsed.y.toFixed(2)})`
}
}
},
scales: {
x: {
title: { display: true, text: 'X Axis' },
grid: { color: 'rgba(0,0,0,0.05)' }
},
y: {
title: { display: true, text: 'Y Axis' },
grid: { color: 'rgba(0,0,0,0.05)' }
}
}
}
};
const myChart = new Chart(document.getElementById('myChart'), config);
</script>⚠️ 注意事项:
- labels 仅对 category、time 或 radialLinear 等部分轴类型有直接影响;在纯 scatter 图中,若所有数据点均以 {x: ..., y: ...} 形式提供,则 labels 不参与坐标计算,但可用于 tooltip、legend 或插件扩展(如标注点名);
- 若需为每个散点添加文本标签(如在点旁显示 'test1'),应使用 Chart.js Plugin Datalabels,而非依赖 data.labels;
- | tojson 是 Jinja2 3.0+ 内置过滤器,无需额外安装;旧版可使用 | safe + json.dumps(),但安全性较低,不推荐。
总结:Chart.js 的 labels 是 data 的一级属性,不是 dataset 的子字段;在 Flask + Jinja2 环境中,务必通过 | tojson 进行序列化,这是保障前后端数据类型一致、避免语法错误的黄金实践。










