Javascript 将JSON数组从Django视图返回到模板
我正在使用Django为一个项目创建一个基于web的应用程序,并且在将数组从Django视图返回到模板时遇到了问题 JavaScript(JQuery)脚本将使用该数组在页面中显示的图像上绘制框。因此,除其他外,此数组将具有要绘制的框的坐标 这是Django视图中用于获取所需数据并将其序列化为JSON的代码:Javascript 将JSON数组从Django视图返回到模板,javascript,python,django,json,Javascript,Python,Django,Json,我正在使用Django为一个项目创建一个基于web的应用程序,并且在将数组从Django视图返回到模板时遇到了问题 JavaScript(JQuery)脚本将使用该数组在页面中显示的图像上绘制框。因此,除其他外,此数组将具有要绘制的框的坐标 这是Django视图中用于获取所需数据并将其序列化为JSON的代码: def annotate(request, ...): ... oldAnnotations = lastFrame.videoannotation_set.filter(
def annotate(request, ...):
...
oldAnnotations = lastFrame.videoannotation_set.filter(ParentVideoLabel=label)
tags = serializers.serialize("json", oldAnnotations)
...
return render_to_response('vannotate.html', {'tags': tags, ...})
作为调试的一种方式,在模板的HTML部分中使用{{{tags}}
可以将其作为输出(很抱歉,行太长):
我假设它是JSON数组的正确格式
稍后在模板中,我尝试在模板的JavaScript部分实际使用标记变量,如下所示:
{% if tags %}
var tagbs = {{ tags|safe }};
var tgs = JSON.parse(tagbs);
alert("done");
{% endif %}
如果我删除var tgs=JSON.parse(tagbs)代码>行,然后警报框会很好地弹出,其余的JavaScript会按预期工作。但是,将这一行保留下来会破坏脚本
我希望能够遍历Django模型中的所有对象,并获得JavaScript中的字段值
我不确定我做错了什么,有人能指出正确的方法吗 您希望对模板中的数据进行JSON加密;JSON实际上已经是Javascript(它是一个子集:
{% if tags %}
var tgs = {{ tags }};
{% endif %}
请注意,标记
已经是JSON(因此是JavaScript)数据,可以直接插入;无需转义(这里没有HTML,而是JavaScript)
或者您可以直接在模板中使用它(无需调用序列化程序。在annotate
方法中序列化
):
针对Django 2.1+和现代web进行编辑和更新:
实现这一点的现代方法是:
1) 将原始数据传递给模板,而不是JSON序列化数据。即:
def annotate(request, ...):
...
oldAnnotations = lastFrame.videoannotation_set.filter(ParentVideoLabel=label)
...
return render_to_response('vannotate.html', {'tags': oldAnnotations, ...})
2) 在模板中,使用新的“json_脚本”过滤器包含json数据:
{{ tags|json_script:"tags-data" }}
这将生成如下所示的HTML:
<script id="tags-data" type="application/json">{"foo": "bar"}</script>
var tags = JSON.parse(document.getElementById('tags-data').textContent);
4) 将Javascript代码移动到外部.js文件中,并设置内容安全策略头以禁止内联Javascript,因为这存在安全风险。请注意,由于json_脚本标记生成json,而不是Javascript,因此它是安全的,并且无论您的内容安全策略设置如何,都是允许的
原始答案:
警告:如果任何字符串由用户控制,则这是不安全的
JSON是Javascript源代码。也就是说,数组的JSON表示是定义数组所需的Javascript源代码
因此,在:
var tagbs = {{ tags|safe }};
tagbs
是包含所需数据的JavaScript数组。不需要调用JSON.parse(),因为web浏览器已经将其解析为JavaScript源代码
所以你应该能做到
var tagbs = {{ tags|safe }};
alert(tagbs[0].fields.ParentVideoFile);
这应该显示“4”
警告:使用这种旧方法,包含“”的字符串将无法工作,它们将出现可怕的错误。这是因为浏览器将视为脚本的结尾。如果任何字符串是用户输入的数据,则这是一个可利用的安全漏洞-。使用上面更现代的方法。您也可以使用django.utils
中的simplejson
。比如:
oldAnnotations = lastFrame.videoannotation_set.filter(ParentVideoLabel=label)
dump = simplejson.dumps(oldAnnotations)
return HttpResponse(dump, mimetype='application/json')
您可以从JS端解析并访问其中的所有数据。您没有将数据发送到JavaScript,而是在服务器端将数据注入脚本,因此代码在客户端被解释为JavaScript。如果查看源代码,您将看到它是一个普通数组文本。在这个上下文中它不是JSON,所以你不能解析它。那个小补丁解决了一切!我是新手,我认为JSON.parse是将JSON变量解析为数组,而不是相反。非常感谢!您不应在此处使用| safe
;这仅用于HTML清理。JSON已经使这个JavaScript安全了,任何HTML内容都不应该转义。|safe
意味着Django不应该试图用HTML转义它-它已经安全了。如果没有这些,Django将用“
替换”
,然后它就会崩溃。@Mike:请注意,在问题中,“标记”已经包含JSON(即它是序列化程序的输出。序列化(“JSON”,…)
或JSON.dumps(…)
)。我认为您传递的是一个原始Python数组,它不起作用。尝试在Python代码中执行json.dumps(…)
,并传递它。如果这不起作用,请尝试创建一个单独的新问题。如果JSON表示包含“”,这可能会导致JS语法无效,如var tagbs={“k”:12,“p”:“”
。我应该将jsonify
过滤器定义放在视图
文件中吗?我试图按照链接上的说明进行操作,但Django告诉我jsonify
过滤器无效。@user2203255:将其放入新的templatetags
子包(一个包含\uuu init\uuuuuuuuuuuuuuuuuuuuuuuuu.py
文件的目录)中,models.py
和视图.py
旁边,请看,这也很好!后来它确实简化了事情。不过有一件事。我必须在safe
(即{{tags | jsonify | safe}}
)中添加一个额外的管道才能让它工作。也许这与我的对象本身有关,我必须解析返回的JSONID字符串:var packet_JSON={{the_packet | jsonify | safe};警报(数据包);var tgs=JSON.parse(packet_JSON);对于(tgs['results']中的e){alert(“First:+e);}@jonicandada:JSON
是JavaScript的一个子集;您不必解析它,它可以直接使用
var tagbs = {{ tags|safe }};
alert(tagbs[0].fields.ParentVideoFile);
oldAnnotations = lastFrame.videoannotation_set.filter(ParentVideoLabel=label)
dump = simplejson.dumps(oldAnnotations)
return HttpResponse(dump, mimetype='application/json')