我正在使用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, ...})
作为调试的一种方式,{{ tags }}在模板的HTML部分中使用会将其作为输出(很抱歉,长行表示):
{{ tags }}
[{"pk": 491, "model": "va.videoannotation", "fields": {"ParentVideoFile": 4, "ParentVideoFrame": 201, "ParentVideoLabel": 4, "top": 220, "height": 30, "width": 30, "ParentVideoSequence": 16, "left": 242}}, {"pk": 492, "model": "va.videoannotation", "fields": {"ParentVideoFile": 4, "ParentVideoFrame": 201, "ParentVideoLabel": 4, "top": 218, "height": 30, "width": 30, "ParentVideoSequence": 16, "left": 307}}]
我认为这是JSON数组的正确格式。
稍后,在模板中,我尝试在模板tags的JavaScript部分中实际使用变量,如下所示:
tags
{% if tags %} var tagbs = {{ tags|safe }}; var tgs = JSON.parse(tagbs); alert("done"); {% endif %}
如果我删除了该var tgs = JSON.parse(tagbs);行,则警报框会正常弹出,其余的JavaScript会按预期工作。但是,保留此行会中断脚本。
var tgs = JSON.parse(tagbs);
我希望能够遍历Django模型中的所有对象并获取JavaScript中字段的值。
我不确定我在这里做错了什么,有人可以指出正确的方法吗?
使用Django 2.1+和现代网络的更新进行编辑:
现代的方法是:
1)将原始数据而不是JSON序列化的数据传递给模板。即:
def annotate(request, ...): ... oldAnnotations = lastFrame.videoannotation_set.filter(ParentVideoLabel=label) ... return render_to_response('vannotate.html', {'tags': oldAnnotations, ...})
2)在您的模板中,使用新的“ json_script”过滤器以包含JSON数据:
{{ tags|json_script:"tags-data" }}
这将导致HTML如下所示:
<script id="tags-data" type="application/json">{"foo": "bar"}</script>
此标记对包含“ script>”的字符串进行了特殊处理,以确保它们可以正常工作。
3)在您的Javascript代码中,获得如下标记数据:
var tags = JSON.parse(document.getElementById('tags-data').textContent);
4)将您的Javascript代码移动到外部.js文件,并设置Content-Security- Policy标头以禁止内联Javascript,因为这存在安全风险。请注意,由于json_script标记生成的是JSON(而不是Javascript),因此它是安全的,并且无论您的Content- Security-Policy设置如何都可以使用。
原始答案:
警告:如果任何字符串是用户控制的,则这是不安全的
JSON 是 Javascript源代码。也就是说,数组的JSON表示是定义数组所需的Javascript源代码。
所以之后:
var tagbs = {{ tags|safe }};
tagbs是包含所需数据的JavaScript数组。无需调用JSON.parse(),因为Web浏览器已将其解析为JavaScript源代码。
tagbs
所以你应该能够做
var tagbs = {{ tags|safe }}; alert(tagbs[0].fields.ParentVideoFile);
并且应该显示“ 4”。
警告:使用这种旧方法,包含“ script>”的字符串将不起作用,它们将导致严重错误。这是因为浏览器会将 script>视为脚本的结尾。如果任何字符串是用户输入的数据,则这是一个可利用的安全漏洞- 有关更多详细信息,请参见此处的注释14。请改用上述更现代的方法。