一尘不染

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

json

我正在使用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部分中使用会将其作为输出(很抱歉,长行表示):

[{"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部分中实际使用变量,如下所示:

{% if tags %}
  var tagbs = {{ tags|safe }};
  var tgs = JSON.parse(tagbs);
  alert("done");
{% endif %}

如果我删除了该var tgs = JSON.parse(tagbs);行,则警报框会正常弹出,其余的JavaScript会按预期工作。但是,保留此行会中断脚本。

我希望能够遍历Django模型中的所有对象并获取JavaScript中字段的值。

我不确定我在这里做错了什么,有人可以指出正确的方法吗?


阅读 320

收藏
2020-07-27

共1个答案

一尘不染

使用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>

此标记对包含“ ”的字符串进行了特殊处理,以确保它们可以正常工作。

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源代码。

所以你应该能够做

var tagbs = {{ tags|safe }};
alert(tagbs[0].fields.ParentVideoFile);

并且应该显示“ 4”。

警告:使用这种旧方法,包含“ ”的字符串将不起作用,它们将导致严重错误。这是因为浏览器会将视为脚本的结尾。如果任何字符串是用户输入的数据,则这是一个可利用的安全漏洞-
有关更多详细信息,请参见此处的注释14。请改用上述更现代的方法。

2020-07-27