Chart.js 中正确传递标签数据的 Jinja 模板实践

11次阅读

Chart.js 中正确传递标签数据的 Jinja 模板实践

在 Flask + Chart.js 项目中,直接将 Python 列表(如 [‘test1’, ‘test2’])通过 {{labels}} 插入 JavaScript 会导致 HTML 实体转义错误(如 &),正确做法是使用 Jinja 的 |tojson 过滤器安全序列化数据。

在 flask + chart.js 项目中,直接将 python 列表(如 `[‘test1’, ‘test2’]`)通过 `{{labels}}` 插入 javascript 会导致 html 实体转义错误(如 `&`),正确做法是使用 jinja 的 `|tojson` 过滤器安全序列化数据。

在 Chart.js(v4+)中,labels 并非 dataset 的属性,而是顶层 data 对象的直属字段。你当前的写法:

datasets: [{type: 'scatter',     labels: {{ labels}}, // ❌ 错误:labels 不属于 dataset     data: {{data}} }]

不仅语义错误(Chart.js 会忽略该字段),更关键的是:当 Jinja 渲染 {{labels}} 时,若 labels = [‘test1’, ‘test2’],默认输出为 [‘test1’, ‘test2’] —— 表面看似合法,但 Flask 的 Jinja 模板引擎 默认会对输出内容进行 HTML 转义(例如将

✅ 正确解法:使用 |tojson 过滤器
该过滤器由 Flask/Jinja 内置提供,能将 Python 对象(列表、字典、字符串等) 安全、无转义地序列化为标准 JSON 字符串,并自动处理引号、Unicode 和特殊字符,生成可直接被 JavaScript 解析的有效字面量。

✅ 正确代码结构(Chart.js v4+ 推荐模式)

<script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <canvas id="myChart"></canvas>  <script>     // ✅ 使用 |tojson 确保 JSON 安全注入     const chartData = {labels: {{ labels | tojson}}, // ? 正确位置:data.labels         datasets: [{                 label: 'Line Trend',                 type: 'line',                 data: [],                 backgroundColor: 'rgb(168, 38, 8)',                 borderColor: 'rgb(168, 38, 8)',                 pointRadius: 0,                 borderWidth: 3,                 order: 2             },             {label: 'Red Points',                 type: 'scatter',                 data: [],                 backgroundColor: 'rgb(168, 38, 8)',                 borderColor: 'rgb(168, 38, 8)',                 pointRadius: 3,                 order: 3             },             {label: 'Green Points',                 type: 'scatter',                 data: [],                 backgroundColor: 'rgb(46, 179, 84)',                 borderColor: 'rgb(46, 179, 84)',                 pointRadius: 3,                 order: 1             },             {label: 'Blue Labels',                 type: 'scatter',                 data: {{ data | tojson}}, // ? 数据也需 tojson                 backgroundColor: 'rgb(52, 110, 235)',                 borderColor: 'rgb(52, 110, 235)',                 pointRadius: 1,                 order: 4             }         ]     };      const config = {type: 'scatter',         data: chartData, // ? 整个 chartData 作为 data 传入         options: {             maintainAspectRatio: true,             aspectRatio: 1,             events: [],             plugins: {legend: { display: false}             },             scales: {x: { display: false},                 y: {display: false}             }         }     };      const myChart = new Chart(document.getElementById('myChart'), config); </script>

⚠️ 关键注意事项

  • labels 必须位于 data 根对象下,而非某个 dataset 内 :Chart.js 的 scatter、line、bar 等图表类型均要求 labels 与 datasets 同级(参考 官方文档)。

  • 所有动态数据都应统一使用 |tojson:包括 data、labels、options 中的动态配置项(如 title.text),避免部分转义、部分未转义导致语法不一致。

  • 确保后端传递的是合法 Python 对象:Flask 视图中应传递原生 list 或 dict,而非 JSON 字符串:

    # ✅ 正确(Python list)return render_template('chart.html', labels=['test1', 'test2'], data=[{x:1,y:2}, {x:3,y:4}])  # ❌ 错误(字符串会被双引号包裹,JSON.parse 失败)# labels=json.dumps(['test1','test2'])
  • 无需额外引入 json 库或手动 JSON.parse():|tojson 输出即为 JS 可执行字面量(如 [“test1″,”test2”]),直接赋值即可。

✅ 验证是否生效

在浏览器开发者工具中查看渲染后的 HTML 源码,确认 labels 行类似:

labels: ["test1", "test2", "test3"],

而非:

labels: ['test1', 'test2', 'test3'],  // ❌ 可能被转义为 &apos;

或包含 “、& 等实体字符。

遵循此模式,即可彻底规避模板注入语法错误,实现 Flask 与 Chart.js 之间安全、健壮的数据传递。

text=ZqhQzanResources