Django传递字典至HTML中JS函数遇类型错误,求解决方案
解决Django字典传递到JS被识别为字符串的问题
你的问题核心在于:Django模板里的{{ t|escapejs }}把Python字典转换成了字符串形式,而不是JS能直接识别的对象。JS会把这个字符串当作普通文本处理,所以Object.keys(test)会返回字符串的字符索引,而不是字典的键。
下面是两种可靠的解决方法,推荐第一种更安全的方案:
方法1:使用Django的json_script模板标签(推荐)
Django内置的json_script标签会帮你把Python数据安全地序列化为JSON,并嵌入到页面中,避免XSS风险,同时能被JS正确解析。
步骤:
- 在HTML模板的任意位置(比如
<script>标签外面)添加:
{{ t|json_script:"test-data" }}
这个标签会生成一个隐藏的<script>标签,ID为test-data,里面是格式化好的JSON字符串。
- 修改你的JS代码,解析这个JSON字符串为JS对象:
google.charts.load('current', {'packages':['table']}); google.charts.setOnLoadCallback(drawTable); // 从json_script生成的标签中获取并解析数据 const test = JSON.parse(document.getElementById('test-data').textContent); const key1 = Object.keys(test)[0]; const top1 = test[key1]; document.getElementById("demo").innerHTML = key1; function drawTable() { var data = new google.visualization.DataTable(); data.addColumn('string', 'Name'); data.addColumn('number', 'Messages Amount'); data.addRows([ // 注意:如果top1是数字,需要转成字符串作为格式化显示值(f字段) [key1, {v: top1, f: top1.toString()}], ['Alice', {v: 12500, f: '$12,500'}], ['Bob', {v: 7000, f: '$7,000'}] ]); var table = new google.visualization.Table(document.getElementById('table_div')); table.draw(data, {showRowNumber: true, width: '100%', height: '100%'}); }
方法2:在视图中提前序列化为JSON
如果你更习惯在后端处理,可以先把Python字典转成JSON字符串,再传递到模板:
步骤:
- 在Django视图中导入
json模块,序列化字典:
import json from django.shortcuts import render def your_view(request): # 假设这是你的字典数据 t = {"John": 12500, "Bob": 7000} # 序列化为JSON字符串 t_json = json.dumps(t) return render(request, "your_template.html", {"t_json": t_json})
- 在模板的JS中直接使用这个JSON字符串(标记为
safe避免转义):
google.charts.load('current', {'packages':['table']}); google.charts.setOnLoadCallback(drawTable); // 直接使用序列化后的JSON,不需要引号,因为它本身就是JS对象格式 const test = {{ t_json|safe }}; const key1 = Object.keys(test)[0]; const top1 = test[key1]; document.getElementById("demo").innerHTML = key1; function drawTable() { var data = new google.visualization.DataTable(); data.addColumn('string', 'Name'); data.addColumn('number', 'Messages Amount'); data.addRows([ [key1, {v: top1, f: top1.toString()}], ['Alice', {v: 12500, f: '$12,500'}], ['Bob', {v: 7000, f: '$7,000'}] ]); var table = new google.visualization.Table(document.getElementById('table_div')); table.draw(data, {showRowNumber: true, width: '100%', height: '100%'}); }
为什么原来的代码不行?
{{ t|escapejs }}只是把Python字典的字符串表示(比如{'John': 12500})转成了JS安全的字符串,但它本质还是字符串。JS不会自动将这个字符串解析为对象,所以test的值是类似"{'John': 12500}"的文本,Object.keys(test)会返回字符串的每个字符的索引(比如["0", "1", "2"...]),test[key1]自然就拿到了单个字符。
内容的提问来源于stack exchange,提问作者user8163099
相关产品推荐
相关产品推荐

