web-dev-qa-db-ja.com

Django=からJavascript DOMにオブジェクトを渡す

Django=からjavascriptを使用してテンプレートにクエリセットを渡そうとしています。

私はこれを解決するためにさまざまなアプローチを試しました:

1。通常のアプローチ-Javascriptは、命名法[&gt Object:ID&lt、&gt Object:ID&lt、...]のために、オブジェクトを解析しようとすることですべて台無しになります

ジャンゴビュー

Django_list = list(Some_Object.objects.all())

テンプレートHTML + JS

<script type="text/javascript" >
    var js_list = {{Django_list}};
</script>

2。JSONアプローチ-DjangoオブジェクトリストからJSON文字列への変換に失敗し、JSONシリアル化できません

ジャンゴビュー

Django_list = list(Some_Object.objects.all())
json_list = simplejson.dumps(Django_list)

テンプレートHTML + JS

<script type="text/javascript" >
    var js_list = {{json_list}};
</script>

だから、私はここでいくつかの助けが必要です:)

誰にも提案/解決策がありますか?

ありがとう!

34
Mc-

OK、解決策を見つけました!

ほとんどの場合、結果を引用しないためでした。 Javascriptがオブジェクトを解析しようとしたとき、これは文字列として認識されませんでした。

したがって、最初のステップは次のとおりです。

var js_list = {{Django_list}}; 

変更後:

var js_list = "{{Django_list}}";

この後、Djangoは文字をエスケープしているので、次のように置き換える必要がありました。

 var myJSONList = (("{{json_list}}").replace(/&(l|g|quo)t;/g, function(a,b){
                return {
                    l   : '<',
                    g   : '>',
                    quo : '"'
                }[b];
            }));

 myData = JSON.parse( myJSONList );

注:Django)から文字をエスケープしないようにしようとしました

var js_list = "{{json_list|safe}}"; 

しかし、引用符と混同されるため、これは機能しません。

最後に、JavaScriptに送信する前にJSONに変換するバックエンドのロジックを回避する方法を見つけました。

var myDjangoList = (("{{Django_list |safe}}").replace(/&(l|g|quo)t;/g, function(a,b){
            return {
                l   : '<',
                g   : '>',
                quo : '"'
            }[b];
        }));

myDjangoList = myDjangoList.replace(/u'/g, '\'')
myDjangoList = myDjangoList.replace(/'/g, '\"')

myData = JSON.parse( myDjangoList );

これは改善できると確信しています。これはあなたにお任せします;)

答えてくれてありがとう

それが他の誰かに役立つことを願っています!

25
Mc-

同じ質問、「より良い」(morecentre)答え: jsonで使用するためのdictへのDjangoクエリセット

vashishtha-jogi による回答:

より良い方法は、DjangoJSONEncoderを使用することです。 Decimalをサポートしています。

import json
from Django.core.serializers.json import DjangoJSONEncoder

prices = Price.objects.filter(product=product).values_list('price','valid_from')

prices_json = json.dumps(list(prices), cls=DjangoJSONEncoder)

とても使いやすい。個々のフィールドをフロートに変換するためのフープをジャンプしません。

更新:simplejsonの代わりに組み込みjsonを使用するように回答を変更しました。

これは私のGoogle検索で非常に頻繁に出された答えであり、非常に多くのビューを持っているので、それを更新して他の人をSOから掘り出さないようにすることをお勧めします。 Django 1.5

29
agconti

Djangoクエリセット areJSONでシリアル化可能 一部のフィールドタイプ(明らかに日付など)は、現時点ではシリアル化できません。日付オブジェクトの回避策は JSONとPythonに関する別の質問 に投稿されています。

JavaScript自体に直接辞書を作成することをお勧めします。次のようなモデルがあります:

class Article(models.Model):
    title = models.CharField(max_length=100)
    slug = models.SlugField()
    content = models.TextField()

class Author(models.Model):
    article = models.ForeignKey("Article", related_name="authors")
    first_name=models.CharField(max_length=100)
    last_name=models.CharField(max_length=100)

テンプレートで次のようなことをします。

<script type="text/javascript">
    var articles = [
    {% for article in article_list %}
        {% if not forloop.first %},{% endif %}
        {
            title: "{{ article.title }}",
            slug: "{{ article.slug }}",
            content: "{{ article.content }}",
            authors: [
            {% for author in article.authors.all %}
                {% if not forloop.first %},{% endif %}
                {
                    first_name: "{{ author.first_name }}",
                    last_name: "{{ author.last_name }}",
                }
            {% endfor %}
            ]
        }
    {% endfor %}
    ]
</script>

もしあなたが質問を少し貧弱に言い、are n't<script>タグと実際にneedJSON何らかの理由で、私は単にビューでループを行い、dictsのリストを作成しますが、JSONは問題ありませんシリアライズ、およびJavaScriptは理解に問題ありません。

8
Jordan Reiter

編集:このメソッドを使用しないでください、@ agcontiの答えを参照してください。

Escapejsフィルターを使用します: https://docs.djangoproject.com/en/1.4/ref/templates/builtins/#escapejs

リストをダンプする例:

var foo = [{% for x in y %}'{{ x|escapejs }}',{% endfor %}]
7
boxed

Djangoの組み込みフィルター safeescapejs の組み合わせを使用できます。

var json_string = unescape({{json_list | safe | escapejs}});
var json_data = JSON.parse(json_string);
6
lguiel

あなたの問題は、多くの場合、あなたの要件が不十分に指定されていることです。 JSONを正確にどのように見せたいですか? 「クエリセットをシリアル化する」と言いますが、どのような形式ですか?各モデルインスタンスのすべてのフィールド、選択、またはUnicode表現のみが必要ですか?その質問に答えると、問題を解決する方法がわかります。

たとえば、1つのアプローチとして、values querysetメソッドを使用して、各インスタンスのフィールドのディクショナリを出力し、それをシリアル化します(最初にリストに変換する必要があります)。

data = SomeObject.objects.values('field1', 'field2', 'field3')
serialized_data = simplejson.dumps(list(data))
4
Daniel Roseman

Django 2.1があるため、 json-script template tag があります。ドキュメントから:

json_script

PythonオブジェクトをJSONとして安全に出力し、タグでラップし、JavaScriptで使用できるようにします。

引数:タグのHTML「id」。

例えば:

{{ value|json_script:"hello-data" }} 

値が辞書の場合{'hello': 'world'}、出力は次のようになります。

<script id="hello-data" type="application/json">
{"hello": "world"}
</script>

結果のデータは、次のようなJavaScriptでアクセスできます。

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

XSS攻撃は、文字「<」、「>」、および「&」をエスケープすることにより軽減されます。たとえば、値が{'hello': 'world</script>&amp;'}、出力は次のとおりです。

<script id="hello-data" type="application/json">
    {"hello": "world\\u003C/script\\u003E\\u0026amp;"}
</script> 

これは、ページ内スクリプトの実行を禁止する厳格なコンテンツセキュリティポリシーと互換性があります。また、パッシブデータと実行可能コードを明確に分離します。

3
LaundroMat

エスケープされていないことを確認するには、文字列を安全としてマークする必要があります。

私のプロジェクトの1つで、次のように使用します。

# app/templatetag/jsonify.py
from Django import template
from Django.utils.safestring import mark_safe
import json

register = template.Library()

@register.filter
def jsonify(list):
    return mark_safe(json.dumps(list))

およびテンプレート内

{% load jsonify %}
<script type="text/javascript" >
    var js_list = {{ python_list|jsonify|escapejs }};
</script>

ただし、mark_safeを追加するか、テンプレートでsafeを使用して、すべての&gt;もの

問題が複雑なpythonオブジェクトの処理に関するものである場合、次のようにハンドラーを実行する必要があります。 JSON datetime between Python and JavaScript

3
christophe31

Djangoは、ここでやろうとしているまさにそのシナリオのための組み込みヘルプを提供します。次のようになります。

ビューにpythonシーケンス、リスト、辞書などがあります。それをpy_object。 1つのアプローチは、レンダリングエンジンに渡す前にjson化することです。

from Django.shortcuts import render_to_response
import json  

その後、このように使用して...

render_to_response('mypage.html',{'js_object':json.dumps(py_object)})

テンプレートで、safeフィルターを使用して、すでにjsonizedされているオブジェクトをpythonからjavascriptにインポートします。このように...

data = {{ js_object|safe }}

これで問題が解決するはずです。

2
nemesisfixx

統合された回答(my env:Django 2.0)

Views.pyで

import json
data= []
// fil the list
context['mydata'] = json.dumps({'data':data})

テンプレート内

  <script type="text/javascript">
      var mydataString = "{{mydata|escapejs}}";
      console.log(JSON.parse(mydataString));
  </script>
0
rogoro