web-dev-qa-db-ja.com

PythonデータをJavaScriptにDjango

DjangoとApacheを使用してWebページを提供します。現在、JavaScriptコードには、選択メニューからのユーザーの選択に基づいてさまざまなHTMLウィジェットに表示される値を持つデータオブジェクトが含まれています。これらのデータをPython辞書から取得します。JavaScriptコードをHTMLに埋め込む方法を知っていると思いますが、そのスクリプトにデータオブジェクトを(オンザフライで)埋め込む方法はスクリプトの機能はそれを使用できますか?

別の言い方をすれば、JavaScriptオブジェクトまたは配列をPython辞書から作成し、そのオブジェクトをJavaScriptコードに挿入してから、そのJavaScriptコードをHTMLに挿入します。

この構造(たとえば、JavaScriptコードの変数に埋め込まれたデータ)は次善だと思いますが、初心者として、私は代替案を知りません。 Djangoシリアル化関数の記事を見てきましたが、そもそもJavaScriptコードにデータを取得できるようになるまで、これらは役に立ちません。

私は(まだ)jQueryのようなJavaScriptライブラリを使用していません。

52
chernevik

n.b.下部の2018アップデートを参照

多くのJavaScriptをDjangoテンプレートに配置することをお勧めします-特にプロジェクトが拡大するにつれて、作成とデバッグが困難になる傾向があります。代わりに、すべてのJavaScriptを別のスクリプトファイルに記述してください。テンプレートが読み込まれ、テンプレートにJSONデータオブジェクトのみが含まれます。これにより、JavaScriptアプリ全体を JSLint などのように実行したり、縮小したりすることができます。 Djangoアプリに依存しない静的なHTMLファイル。simplejsonのようなライブラリを使用すると、面倒なシリアル化コードの記述に費やす時間も節約できます。

AJAXアプリを構築していると想定していない場合、これは次のように簡単に実行できます。

ビューで:

_from Django.utils import simplejson


def view(request, …):
    js_data = simplejson.dumps(my_dict)
    …
    render_template_to_response("my_template.html", {"my_data": js_data, …})
_

テンプレート内:

_<script type="text/javascript">
    data_from_Django = {{ my_data }};
    widget.init(data_from_Django);
</script>
_

データのタイプが重要であることに注意してください:_my_data_が、書式設定された日付など、HTMLを含まない単純な数値または制御されたソースからの文字列である場合、特別な処理は不要です。ユーザーから信頼できないデータが提供される可能性がある場合は、 escape または escapejs フィルターなどを使用してサニタイズし、回避するためにJavaScriptがデータを安全に処理するようにする必要があります クロスサイトスクリプティング 攻撃。

日付に関する限り、日付をどのように渡すかについて考えることもできます。ほとんどの場合、Unixタイムスタンプとして渡すのが最も簡単です。

Djangoの場合:

_time_t = time.mktime(my_date.timetuple())
_

JavaScriptで、上記のスニペットの結果で_time_t = {{ time_t }}_のようなことをしたと仮定します。

_my_date = new Date();
my_date.setTime(time_t*1000);
_

最後に、UTCに注意してください-PythonとDjango日付関数はUTCでデータを交換して、ユーザーの現地時間からの恥ずかしいシフトを避けることができます。

編集:javascriptのsetTimeはミリ秒単位ですが、time.mktimeの出力は秒単位です。それが1000倍する必要がある理由です

2018年の更新:複雑な値のJSONがまだ好きですが、10年の間に HTML5データAPI が達成されました ユニバーサルブラウザーサポートに近い そして、単純な(リスト以外の)を渡すのに非常に便利です/ dict)の値。特に、それらの値に基づいてCSSルールを適用したい場合、サポートされていないバージョンのInternet Explorerを気にしない場合。

_<div id="my-widget" data-view-mode="tabular">…</div>

let myWidget = document.getElementById("my-widget");
console.log(myWidget.dataset.viewMode); // Prints tabular
somethingElse.addEventListener('click', evt => {
    myWidget.dataset.viewMode = "list";
});
_

これは、Djangoテンプレートに初期ビューステートを設定し、JavaScriptが_data-_属性を更新するときに自動的に更新する場合にデータをCSSに公開するための適切な方法です。これは、ユーザーが処理するものを選択するまでプログレスウィジェットを非表示にする、フェッチ結果に基づいてエラーを条件付きで表示/非表示にする、または#some-element::after { content: attr(data-active-transfers); }などのCSSを使用してアクティブレコードカウントを表示するなどの場合に使用します。

78
Chris Adams

これで問題が発生する可能性がある場合は、テンプレートのセーフモードでjsonオブジェクトをレンダリングしていることを確認してください。このように手動で設定できます

<script type="text/javascript">
    data_from_Django = {{ my_data|safe }};
    widget.init(data_from_Django);
</script>
38
wilblack

.htmlテンプレート内に<script>タグを含めて、データ構造を構築することができますが、便利です。テンプレート言語はHTMLだけでなく、Javascriptオブジェクトリテラルも実行できます。

Paulは正しい。jsonモジュールを使用してJSON文字列を作成し、その文字列をテンプレートに挿入するのが最善かもしれません。これにより、引用の問題を最適に処理し、深い構造を簡単に処理できます。

3
Ned Batchelder

それは次善です。そのためにDjangoの組み込みシリアライザーを使用してデータをJSONとして渡すことを検討しましたか?

2
Paul McMillan

この質問 に関連する応答を参照してください。 1つのオプションは、 jsonpickle を使用してPythonオブジェクトとJSON/Javascriptオブジェクトの間をシリアル化します。simplejsonをラップし、simplejsonで通常受け入れられないものを処理します。

1
John Paulett

2018年半ばの時点で、最も単純なアプローチはpythonのjsonモジュールを使用することです。simplejsonは非推奨になりました。 @wilblackが述べているように、safeフィルターまたはautoescapeオプション付きのoffタグを使用してDjangoの自動エスケープを防ぐ必要があることに注意してください。どちらの場合も、ビューで辞書の内容をコンテキストに追加します

viewset.py

import json def get_context_data(self, **kwargs): context['my_dictionary'] = json.dumps(self.object.mydict)

そして、@ wilblackが示唆するようにテンプレートに追加します:

template.html

<script> my_data = {{ my_dictionary|safe }}; </script>

1
Daniel Kislyuk

Javaに埋め込まれたスクリプトDjangoテンプレートはむしろ常に悪い考えです。

むしろ。このルールにはいくつかの例外があるためです。

すべてはJavaスクリプトコードサイトと機能に依存します。

JSのように静的ファイルを個別に用意する方が適切ですが、問題はすべての個別ファイルに別の接続/ GET /要求/応答メカニズムが必要なことです。時々、小さなライナーの場合、2つのライナーがJSを使用してこれをテンプレートに入れ、バンを使用してDjango templatetagsメカニズム-他のテンプレートで使用できます;)

オブジェクトについて-同じ。あなたのサイトにAJAX construction/web2.0が好意を持っている場合-クライアント側にカウント/数学演算を置く非常に良い効果を達成できます。オブジェクトが小さい場合-テンプレートに埋め込まれている場合、大きい場合-別の接続で応答して、ユーザーのハングアップページを回避します。

1
bluszcz