Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
271 views
in Technique[技术] by (71.8m points)

javascript - Returning JSON array from a Django view to a template

I'm using Django to create a web-based app for a project, and I'm running into issues returning an array from a Django view to a template.

The array will be used by a JavaScript (JQuery) script for drawing boxes on an image shown in the page. Therefore, this array will have, among other things, coordinates for the boxes to be drawn.

This is the code in the Django view used to get the required data and serialize it as JSON:

def annotate(request, ...):
    ...
    oldAnnotations = lastFrame.videoannotation_set.filter(ParentVideoLabel=label)
    tags = serializers.serialize("json", oldAnnotations)
    ...
    return render_to_response('vannotate.html', {'tags': tags, ...})

As a way of debugging, using {{ tags }} in the HTML portion of the template gives this as output (sorry for the long line):

[{"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}}]

which I assume is the correct format for a JSON array.

Later on in the template, I attempt to actually use the tags variable in the JavaScript portion of the template, as follows:

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

If I remove the var tgs = JSON.parse(tagbs); line, then the alert box pops up fine, and the rest of the JavaScript works as expected. Leaving this line in breaks the script, however.

I want to be able to iterate through all the objects in the Django model and get values of fields in JavaScript.

I'm not sure what I'm doing wrong here, could someone point out the right way to do this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Edit with update for Django 2.1+ and the modern web:

The modern way to do this is:

1) Pass the raw data to the template, not the JSON-serialised data. I.e.:

def annotate(request, ...):
    ...
    oldAnnotations = lastFrame.videoannotation_set.filter(ParentVideoLabel=label)
    ...
    return render_to_response('vannotate.html', {'tags': oldAnnotations, ...})

2) In your template, use the new "json_script" filter to include the JSON data:

{{ tags|json_script:"tags-data" }}

That will result in HTML that looks like this:

<script id="tags-data" type="application/json">{"foo": "bar"}</script>

This tag has special handling of strings containing "</script>" to make sure they work.

3) In your Javascript code, get that tags data like this:

var tags = JSON.parse(document.getElementById('tags-data').textContent);

4) Move your Javascript code to an external .js file, and set up the Content-Security-Policy header to prohibit inline Javascript because it's a security risk. Note that since the json_script tag generates JSON, not Javascript, it's safe and is allowed regardless of your Content-Security-Policy setting.

Original Answer:

WARNING: If any of the strings are user-controlled, this is insecure

JSON is Javascript source code. I.e. the JSON representation of an array is the Javascript source code you need to define the array.

So after:

var tagbs = {{ tags|safe }};

tagbs is a JavaScript array containing the data you want. There's no need to call JSON.parse(), because the web browser already parsed it as JavaScript source code.

So you should be able to do

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

and that should show "4".

WARNING: With this old method, strings containing "</script>" will not work, they will go horribly wrong. This is because the browser will treat </script> as the end of the script. If any of the strings are user-entered data, this is an exploitable security flaw - see comment 14 here for more details. Use the more modern method above, instead.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...