Django中POST请求更新保存赛事字典的JSON格式问题
解决Django+JS赛事对阵图的JSON格式转换问题
我来帮你一步步排查这个JSON相关的问题,核心原因就是前后端在JSON序列化/反序列化环节不匹配,导致了前端语法错误和后端解码失败。
一、先解决前端$.post的语法错误
你遇到的Uncaught SyntaxError: Invalid or unexpected token,大概率是因为前端没有正确构造标准JSON字符串就发送请求,或者没有告诉后端你发的是JSON数据。
正确的前端写法
首先,确保从Django模板获取赛事数据时用安全的方式,推荐用Django的json_script标签(避免XSS和格式混乱):
<!-- 在模板中添加这行,把Python字典转成安全的JSON字符串嵌入页面 --> {{ bracket|json_script:"bracket-data" }}
然后在JS里正确读取并发送数据:
// 从页面获取赛事数据并转成JS对象 const rawBracket = document.getElementById('bracket-data').textContent; const bracketData = JSON.parse(rawBracket); // 假设你已经修改了bracketData,现在提交更新 $.post({ url: '/update_bracket/', contentType: 'application/json', // 关键:告诉后端这是JSON格式 data: JSON.stringify(bracketData), // 把JS对象转成标准JSON字符串(必须双引号) success: function() { window.location.href = '/bracket/'; // 重定向回对阵图页面 }, error: function(xhr) { console.error('更新失败:', xhr.responseText); } });
为什么之前会报错?
- 如果直接传递JS对象而不用
JSON.stringify,jQuery会把它转成表单格式(key=value&...),不是JSON - 如果手动拼接JSON字符串用了单引号(比如
'{ "key": 'value' }'),这不符合JSON标准(必须双引号包裹属性名和字符串值)
二、修复后端update_bracket视图的JSONDecodeError
前端正确发送JSON后,后端不能再用request.POST读取数据(request.POST是用来处理表单的),要直接读取请求体的原始JSON字符串:
import json from django.shortcuts import redirect from django.http import JsonResponse from .models import Employee def update_bracket(request): if request.method != 'POST': return JsonResponse({'error': '仅接受POST请求'}, status=400) try: # 从请求体读取原始JSON并转成Python字典 bracket_data = json.loads(request.body) # 保存到Employee的JSONField(直接存字典就行,Django会自动序列化) # 这里替换成你实际获取Employee对象的逻辑 employee = Employee.objects.get(user=request.user) employee.bracket = bracket_data employee.save() return redirect('bracket') # 重定向回对阵图视图 except json.JSONDecodeError as e: return JsonResponse({'error': f'JSON解码失败: {str(e)}'}, status=400) except Employee.DoesNotExist: return JsonResponse({'error': '未找到对应员工'}, status=404)
注意:Django的JSONField本身支持直接存储Python字典,不需要你手动转成JSON字符串,它会自动处理序列化和反序列化。
三、检查Tournament类生成的字典格式
还要确保你的Tournament类生成的字典是JSON可序列化的,不能包含Python专属类型:
- 比如
datetime对象要转成ISO字符串(date.isoformat()) Decimal类型要转成float或字符串- 不能有自定义类实例、函数这类无法序列化的对象
示例修复:
class Tournament: def generate_bracket(self): bracket = { "rounds": [ { "matches": [ { "team1": "Team A", "team2": "Team B", "match_date": self.match_date.isoformat(), # 转成JSON支持的字符串 "score": {"team1": 2, "team2": 1} } ] } ] } return bracket
四、常见坑点总结
- 前端必须用
JSON.stringify()转成标准JSON,同时设置contentType: 'application/json' - 后端必须读取
request.body,而不是request.POST - 确保传递的数据里没有Python专属类型,全部是JSON支持的类型(字符串、数字、列表、字典、布尔值、null)
- 模板传递JSON用
json_script标签,比直接{{ bracket|safe }}更安全
内容的提问来源于stack exchange,提问作者amchugh89
相关产品推荐
相关产品推荐

