Javascript 将JSON数组从Django视图返回到模板

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(

我正在使用Django为一个项目创建一个基于web的应用程序,并且在将数组从Django视图返回到模板时遇到了问题

JavaScript(JQuery)脚本将使用该数组在页面中显示的图像上绘制框。因此,除其他外,此数组将具有要绘制的框的坐标

这是Django视图中用于获取所需数据并将其序列化为JSON的代码:

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')