29

Djangoを使用してプロジェクト用のWebベースのアプリを作成していますが、Djangoビューからテンプレートに配列を返す際に問題が発生しています。

この配列は、ページに表示されている画像にボックスを描画するためのJavaScript(JQuery)スクリプトによって使用されます。したがって、この配列には、特に、描画されるボックスの座標が含まれます。

これは、必要なデータを取得してJSONとしてシリアル化するために使用されるDjangoビューのコードです。

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のフィールドの値を取得できるようにしたいと思います。

ここで何が間違っているのかわかりませんが、誰かがこれを行う正しい方法を指摘できますか?

4

3 に答える 3

43

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_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 タグは Javascript ではなく JSON を生成するため、Content-Security-Policy の設定に関係なく安全で許可されていることに注意してください。

元の回答:

警告: 文字列のいずれかがユーザーによって制御されている場合、これは安全ではありません

JSONJavascript ソース コードです。つまり、配列の JSON 表現は、配列を定義するために必要な Javascript ソース コードです。

だから後:

var tagbs = {{ tags|safe }};

tagbs必要なデータを含む JavaScript 配列です。JSON.parse() を呼び出す必要はありません。これは、Web ブラウザーが既に JavaScript ソース コードとして解析しているためです。

だからあなたはできるはずです

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

「4」と表示されるはずです。

警告: この古い方法では、"</script>" を含む文字列は機能しません。これは、ブラウザーが </script> をスクリプトの末尾として扱うためです。文字列のいずれかがユーザーが入力したデータである場合、これは悪用可能なセキュリティ上の欠陥です。詳細については、こちらのコメント 14 を参照してください。代わりに、上記のより現代的な方法を使用してください。

于 2013-03-23T22:36:34.427 に答える
4

テンプレート内のデータを JSON 化する必要があります。JSON はすでに実際には Javascript です (サブセットです:

{% if tags %}
  var tgs = {{ tags }};
{% endif %}

tagsはすでに JSON (したがって JavaScript) データであり、直接挿入できることに注意してください。エスケープする必要はありません (ここには HTML はなく、代わりに JavaScript です)。

または、このDjango スニペットを使用して、テンプレートで直接実行することもできます (メソッドで呼び出す必要はありません) serializers.serializeannotate

var tgs = {{ tags|jsonify }};
于 2013-03-23T22:36:24.250 に答える
2

simplejsonからも使用できますdjango.utils。好き:

oldAnnotations = lastFrame.videoannotation_set.filter(ParentVideoLabel=label)
dump = simplejson.dumps(oldAnnotations)

return HttpResponse(dump, mimetype='application/json')

これでJS側からすべてのデータを解析して到達できます。

于 2013-03-23T23:47:05.100 に答える