
在 Django 视图中手动构造 Python 字典列表并直接传入模板,会导致 HTML 属性中出现单引号格式的字符串(如 {'weight': '122.00'}),这不是合法 JSON,前端 JSON.parse() 会报错;应使用 json.dumps() 或 Django 内置 |json_script 过滤器生成标准双引号 JSON。
在 django 视图中手动构造 python 字典列表并直接传入模板,会导致 html 属性中出现单引号格式的字符串(如 `{'weight': '122.00'}`),这不是合法 json,前端 `json.parse()` 会报错;应使用 `json.dumps()` 或 django 内置 `|json_script` 过滤器生成标准双引号 json。
Django 模板默认将 Python 对象以 repr() 形式渲染(如单引号、无转义),这不是 JSON,不能被 JavaScript 安全解析。要实现前后端可靠数据传递,必须确保输出的是符合 RFC 8259 的标准 JSON 字符串——即键和字符串值均使用双引号,且特殊字符已正确转义。
✅ 正确做法一:在视图中使用 json.dumps()
首先导入标准库 json,然后对数据结构调用 dumps():
import json
from django.core.paginator import Paginator
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
@login_required
def profile_page(request):
# ... 表单处理逻辑(略)...
user_weight_log = WeightRecord.objects.filter(
profile__user=request.user
).order_by('-entry_date')
paginator = Paginator(user_weight_log, 10)
page = request.GET.get('page')
try:
user_weight_log = paginator.page(page)
except PageNotAnInteger:
user_weight_log = paginator.page(1)
except EmptyPage:
user_weight_log = paginator.page(paginator.num_pages)
# ✅ 使用 json.dumps() 生成标准 JSON 字符串
serialized_data = json.dumps([
{
'weight': str(record.weight),
'entry_date': record.entry_date.strftime('%Y-%m-%d')
}
for record in user_weight_log
])
return render(request, 'profile.html', {
'user_weight_log': user_weight_log,
'form': form,
'weight_data': serialized_data # ← 已是合法 JSON 字符串
})对应模板中,仍需 |safe(因 json.dumps() 输出含双引号和转义符的纯字符串,Django 会自动转义 <, > 等,破坏 JSON):
<div id="weight-data" data-weight-data="{{ weight_data|safe }}"></div>前端 JavaScript 可安全解析:
立即学习“Python免费学习笔记(深入)”;
const weightDataElement = document.getElementById('weight-data');
const weightDataJSON = weightDataElement.getAttribute('data-weight-data');
const weightData = JSON.parse(weightDataJSON); // ✅ 成功解析为数组
console.log(weightData[0].weight); // "122.00"✅ 正确做法二(推荐):使用 Django |json_script 过滤器(Django ≥ 3.1)
更安全、更语义化的方式是借助 Django 内置的 json_script 模板过滤器,它自动处理转义、编码与 DOM 安全性,并将数据嵌入 <script type="application/json"> 标签中:
视图保持原样(无需 json.dumps):
# 在视图中直接传入 Python 列表(无需序列化)
serialized_data = [
{'weight': str(record.weight), 'entry_date': record.entry_date.strftime('%Y-%m-%d')}
for record in user_weight_log
]
return render(request, 'profile.html', {
'user_weight_log': user_weight_log,
'form': form,
'weight_data': serialized_data # ← 仍是 Python list/dict
})模板中使用过滤器:
{{ weight_data|json_script:"weight-data" }}这将渲染为:
<script id="weight-data" type="application/json">[{"weight": "122.00", "entry_date": "2023-09-28"}, ...]</script>前端读取(简洁且防 XSS):
const weightDataElement = document.getElementById('weight-data');
const weightData = JSON.parse(weightDataElement.textContent);⚠️ 注意事项:
- *永远不要在 `data-属性中直接插入未序列化的 Python 对象**(如{{ weight_data }}`),这是常见陷阱;
- |json_script 是目前最推荐的方式:它避免了内联脚本风险、自动处理 Unicode 和特殊字符、无需手动 |safe;
- 若必须用 data-* 属性,请确保服务端使用 json.dumps() + 模板 |safe,并验证输出是否为合法 JSON(可用 JSONLint 校验);
- 所有日期、数值建议统一格式化(如 ISO 8601 字符串),避免前端解析歧义。
通过以上任一方式,即可彻底解决 JSON.parse: expected property name 错误,实现 Django 后端到前端 JavaScript 的健壮数据传递。


















