最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Python Django 中安全序列化数据提供给前端 JSON 解析的完整实践
时间:2026-06-15 09:38:58 编辑:袖梨 来源:一聚教程网
本文详解如何在 Django 视图中正确将 Python 数据结构序列化为标准 JSON 字符串(而非 Python 字面量),避免因单引号导致 JSON.parse() 失败,并推荐两种生产级方案:json.dumps() 手动序列化与 Django 内置 |json_script 模板过滤器。
本文详解如何在 django 视图中正确将 python 数据结构序列化为标准 json 字符串(而非 python 字面量),避免因单引号导致 `json.parse()` 失败,并推荐两种生产级方案:`json.dumps()` 手动序列化与 django 内置 `|json_script` 模板过滤器。
在 Django 开发中,常需将后端查询的数据(如用户体重记录)传递给前端 JavaScript 进行可视化渲染(例如使用 Chart.js 绘制趋势图)。但若直接在模板中通过 {{ weight_data|safe }} 渲染 Python 列表字典,Django 会输出类似 [{'weight': '122.00', 'entry_date': '2023-09-28'}] 的字符串——这不是合法 JSON:JSON 标准强制要求键名和字符串值必须使用双引号("),而 Python 的 repr() 输出默认使用单引号('),导致前端调用 JSON.parse() 时抛出 SyntaxError。
✅ 正确方案一:视图层使用 json.dumps() 序列化
在视图中引入 Python 标准库 json,用 dumps() 显式生成符合 RFC 8259 的 JSON 字符串:
from json import dumps # ✅ 关键导入# ... 其他逻辑(分页、查询等)保持不变 ...# 替换原 serialized_data 赋值语句:serialized_data = dumps([ { 'weight': float(record.weight), # 推荐保留数值类型,避免后续 parseFloat() 'entry_date': record.entry_date.isoformat() # 更健壮的日期格式(ISO 8601) } for record in user_weight_log])
? 注意:dumps() 默认不转义 HTML 特殊字符。若数据含 <, >, & 等,建议添加 separators=(',', ':') 减少空格,并确保模板中仍使用 |safe(因 JSON 字符串本身不含 HTML 标签,安全)。
模板中保持原写法:
立即学习“Python免费学习笔记(深入)”;
<div id="weight-data" data-weight-data="{{ weight_data|safe }}"></div>
前端 JavaScript 可安全解析:
const weightDataElement = document.getElementById('weight-data');const weightDataJSON = weightDataElement.getAttribute('data-weight-data');const weightData = JSON.parse(weightDataJSON); // ✅ 成功!console.log(weightData[0].weight); // number: 122
✅ 正确方案二:模板层使用 |json_script(推荐!)
Django 4.2+ 提供了更安全、更现代的解决方案:|json_script 过滤器。它自动序列化数据为 <script type="application/json"> 块,规避 XSS 风险且无需手动处理引号或转义。
视图中直接传入 Python 对象(无需 dumps):
# 视图中保持原始列表推导式(不调用 dumps)weight_data = [ {'weight': float(record.weight), 'entry_date': record.entry_date.isoformat()} for record in user_weight_log]return render(request, 'profile.html', { 'user_weight_log': user_weight_log, 'form': form, 'weight_data': weight_data # ✅ 传入原生 Python list/dict})
模板中使用 |json_script:
<!-- 生成一个带 ID 的 script 标签 -->{{ weight_data|json_script:"weight-data" }}
前端通过 JSON.parse() 读取:
// 自动查找 ID 为 "weight-data" 的 script 标签并解析其内容const weightData = JSON.parse(document.getElementById('weight-data').textContent);console.log(weightData.length); // ✅ 正确解析为数组
✅ 优势总结:
- ✨ 自动 HTML 转义,杜绝 XSS(即使数据含恶意脚本也不会执行);
- ? 语义化 <script type="application/json"> 符合规范;
- ? 无需在视图中导入 json,逻辑更清晰;
- ? 支持任意嵌套结构(dict/list/tuple/None/bool/int/float),无需手动处理类型。
⚠️ 注意事项与最佳实践
- 永远不要对未序列化的 Python 对象使用 |safe:{{ weight_data|safe }} 仅适用于已确认为合法 JSON 字符串的变量(如 dumps() 输出),否则存在安全风险。
- 日期格式优先用 isoformat():比 strftime('%Y-%m-%d') 更通用,JavaScript new Date() 可直接解析。
- 数值类型保持原生:用 float(record.weight) 而非 str(),避免前端重复 parseFloat()。
- 分页数据需谨慎:当前示例中 user_weight_log 是 Page 对象,|json_script 会自动序列化其 object_list,但若需总页数等元信息,应额外构造字典传递。
通过以上任一方案,即可彻底解决单引号 JSON 解析错误,实现 Django 后端与前端 JavaScript 的安全、高效数据互通。
相关文章
- 伊莫星骑士支线任务如何完成 06-16
- 逆战未来深渊狂潮怎么玩 06-16
- 银河灰暗角落结局彩蛋触发方法分享 06-16
- 异能重组护盾流玩法攻略介绍说明 06-16
- 别拽了烤串师傅气味炸弹成就解锁攻略 06-16
- 银河灰暗角落暴击流玩法构筑分享 06-16