Djangoテンプレート変数とJavascript
-
08-07-2019 - |
質問
Djangoテンプレートレンダラーを使用してページをレンダリングするとき、{{ myVar }}
を使用してページ内でそれらを操作するために、さまざまな値を含む辞書変数を渡すことができます。
Javascriptで同じ変数にアクセスする方法はありますか(おそらくDOMを使用して、Djangoが変数にアクセス可能にする方法がわかりません)。渡された変数に含まれる値に基づいてAJAXルックアップを使用して詳細をルックアップできるようにしたい。
解決
{{variable}}
はHTMLに直接置き換えられます。ソースを表示します。 <!> quot; variable <!> quotではありません。またはそのようなもの。テキストをレンダリングしただけです。
とはいえ、この種の置換をJavaScriptに入れることができます。
<script type="text/javascript">
var a = "{{someDjangoVariable}}";
</script>
これにより、<!> quot; dynamic <!> quot; javascript。
他のヒント
注意チケット#17419 で、同様のタグの追加に関する説明を確認してください。 Djangoコアと、ユーザーが生成したデータでこのテンプレートタグを使用することによって導入される可能性のあるXSSの脆弱性を調べます。 amacneilのコメントでは、チケットで発生した懸念のほとんどについて説明しています。
これを行う最も柔軟で便利な方法は、JSコードで使用する変数のテンプレートフィルターを定義することです。これにより、データが適切にエスケープされ、dict
やlist
などの複雑なデータ構造で使用できるようになります。そのため、多くの賛成票が寄せられた回答が受け入れられているにもかかわらず、この回答を書いています。
テンプレートフィルタの例を次に示します。
// myapp/templatetags/js.py
from django.utils.safestring import mark_safe
from django.template import Library
import json
register = Library()
@register.filter(is_safe=True)
def js(obj):
return mark_safe(json.dumps(obj))
このテンプレートフィルタは、変数をJSON文字列に変換します。次のように使用できます:
// myapp/templates/example.html
{% load js %}
<script type="text/javascript">
var someVar = {{ some_var | js }};
</script>
私のために働いた解決策は、テンプレートの非表示の入力フィールドを使用することです
<input type="hidden" id="myVar" name="variable" value="{{ variable }}">
この方法でJavaScriptの値を取得する
var myVar = document.getElementById("myVar").value;
Djangoによって変数が返されると、すべての引用符が"
に変換されます。 {{someDjangoVariable|safe}}
を使用すると、Javascriptエラーが発生します。
これを修正するには、JavaScriptを使用します.replace
:
<script type="text/javascript">
var json = "{{someDjangoVariable}}".replace(/"/g,"\"")
</script>
辞書の場合、最初にJSONにエンコードするのが最適です。 simplejson.dumps()を使用できます。AppEngineのデータモデルから変換する場合は、GQLEncoderライブラリのencode()を使用できます。
Django 2.1では、この使用例専用の新しい組み込みテンプレートタグjson_script
。
https://docs.djangoproject.com/en /2.1/ref/templates/builtins/#json-script 。
新しいタグはテンプレート値を安全にシリアル化し、XSSから保護します。
これは私が非常に簡単にやっていることです: テンプレートのbase.htmlファイルを変更し、それを下部に配置しました:
{% if DJdata %}
<script type="text/javascript">
(function () {window.DJdata = {{DJdata|safe}};})();
</script>
{% endif %}
次に、javascriptファイルで変数を使用する場合、DJdata辞書を作成し、jsonによってコンテキストに追加します:context['DJdata'] = json.dumps(DJdata)
お役に立てばと思います!
私は似たような問題に直面していましたが、S.Lottによって提案された答えは私のために働きました。
<script type="text/javascript">
var a = "{{someDjangoVariable}}"
</script>
ただし、ここで主要な実装制限を指摘したいと思います。 JavaScriptコードを別のファイルに入れて、そのファイルをテンプレートに含めることを計画している場合。これは機能しません。
これは、メインテンプレートとjavascriptコードが同じファイルにある場合にのみ機能します。 おそらくdjangoチームはこの制限に対処できます。
これにも苦労しています。表面的には、上記のソリューションが機能するはずです。ただし、djangoアーキテクチャでは、各htmlファイルに独自のレンダリング変数が必要です(つまり、{{contact}}
はcontact.html
にレンダリングされ、{{posts}}
はindex.html
などにレンダリングされます)。一方、<script>
タグは、{%endblock%}
およびbase.html
が継承する<script src="static/js/somecode.js"></script>
の<=>の後に表示されます。これは基本的に、
<script type="text/javascript">
var myVar = "{{ myVar }}"
</script>
は、変数とスクリプトが同じファイル内に共存できないため、失敗することになります。
私が最終的に思いついた、そして私のために働いた簡単な解決策は、変数をidのタグで単純にラップし、後でjsファイルでそれを参照することでした:
// index.html
<div id="myvar">{{ myVar }}</div>
そして:
// somecode.js
var someVar = document.getElementById("myvar").innerHTML;
通常のように<=>に<=>を含めるだけです。 もちろん、これはコンテンツの取得についてのみです。セキュリティに関しては、他の回答に従ってください。
Djangoフィールドにテキストとして保存されたJavaScriptオブジェクトの場合、再びページ上のスクリプトに動的に挿入されるJavaScriptオブジェクトになる必要があるため、escapejs
とJSON.parse()
の両方を使用する必要があります。
var CropOpts = JSON.parse("{{ profile.last_crop_coords|escapejs }}");
Djangoの<=>はクォートを適切に処理し、<=>は文字列をJSオブジェクトに変換します。
外部の.jsスクリプトに変数を渡す場合は、スクリプトタグの前に、グローバル変数を宣言する別のスクリプトタグを置く必要があることに注意してください。
<script type="text/javascript">
var myVar = "{{ myVar }}"
</script>
<script type="text/javascript" src="{% static "scripts/my_script.js" %}"></script>
data
は、通常どおりget_context_data
def get_context_data(self, *args, **kwargs):
context['myVar'] = True
return context