将对象从Django传递到Javascript DOM

Mc-*_*Mc- 37 javascript python django json dom

我正在尝试将一个来自Django的查询集传递给一个带有javascript的模板.

我尝试过不同的方法来解决这个问题:

1.正常方法 - 由于命名法,Javascript会因为尝试解析对象而搞得一团糟[> Object:ID<> Object:ID< ...]

Django View

django_list = list(Some_Object.objects.all())
Run Code Online (Sandbox Code Playgroud)

模板HTML + JS

<script type="text/javascript" >
    var js_list = {{django_list}};
</script>
Run Code Online (Sandbox Code Playgroud)

2. JSON方法 - Django无法将对象列表转换为json字符串,而不是JSON可序列化的

Django View

django_list = list(Some_Object.objects.all())
json_list = simplejson.dumps(django_list)
Run Code Online (Sandbox Code Playgroud)

模板HTML + JS

<script type="text/javascript" >
    var js_list = {{json_list}};
</script>
Run Code Online (Sandbox Code Playgroud)

所以,我需要一些帮助:)

有人有任何建议/解决方案吗?

谢谢!

agc*_*nti 29

同样的问题,"更好"(更近期)回答:Django Queryset dict在json中使用

通过回答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)
Run Code Online (Sandbox Code Playgroud)

非常好用.没有跳过箍将单个字段转换为浮点数.

更新:更改了使用builtin json而不是simplejson的答案.

这个答案在我的谷歌搜索中经常出现,并且有很多观点,这似乎是一个好主意,更新它并保存其他任何人从挖掘SO.假设Django 1.5.


Mc-*_*Mc- 25

好的,我找到了解决方案!

主要是因为没有引用结果.当Javascript试图解析对象时,这不被识别为字符串.

所以,第一步是:

var js_list = {{django_list}}; 
Run Code Online (Sandbox Code Playgroud)

变成:

var js_list = "{{django_list}}";
Run Code Online (Sandbox Code Playgroud)

在此之后,我意识到Django正在逃避角色,所以我必须像这样替换它们:

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

 myData = JSON.parse( myJSONList );
Run Code Online (Sandbox Code Playgroud)

注意:我试图避免使用以下方法从Django中转义字符:

var js_list = "{{json_list|safe}}"; 
Run Code Online (Sandbox Code Playgroud)

但这不起作用,因为它与引号混淆.

最后,我找到了一种方法来避免在将其发送到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 );
Run Code Online (Sandbox Code Playgroud)

我相信这可以改进,我告诉你;)

谢谢你的回答

希望对别人有帮助!

  • 这个答案不是一个优雅的方法.试试http://stackoverflow.com/questions/10502135/django-queryset-to-dict-for-use-in-json (2认同)

Jor*_*ter 8

Django的查询集序列化化JSON.某些字段类型(例如日期,显然),无法序列化.日期对象的解决方法发布在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)
Run Code Online (Sandbox Code Playgroud)

我会在模板中做这样的事情:

<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>
Run Code Online (Sandbox Code Playgroud)

如果您的问题可能有点差,并且不打算在代码中插入代码<script>并且由于某种原因实际上需要 JSON,我只需在视图中执行循环并创建一个dicts 列表,JSON没有问题序列化,和JavaScript没有问题的理解.


box*_*xed 7

编辑:请不要使用这种方法,请参阅@ agconti的答案.

使用escapejs过滤器:https://docs.djangoproject.com/en/1.4/ref/templates/builtins/#escapejs

转储列表的示例:

var foo = [{% for x in y %}'{{ x|escapejs }}',{% endfor %}]
Run Code Online (Sandbox Code Playgroud)


Lau*_*Mat 7

从 Django 2.1 开始,就有了json-script 模板标签。从文档:

json_script

安全地将 Python 对象输出为 JSON,包装在标签中,准备与 JavaScript 一起使用。

参数:标签的 HTML“id”。

例如:

{{ value|json_script:"hello-data" }} 
Run Code Online (Sandbox Code Playgroud)

如果 value 是 dictionary {'hello': 'world'},则输出将为:

<script id="hello-data" type="application/json">
{"hello": "world"}
</script>
Run Code Online (Sandbox Code Playgroud)

可以像这样在 JavaScript 中访问结果数据:

var value = JSON.parse(document.getElementById('hello-data').textContent); 
Run Code Online (Sandbox Code Playgroud)

XSS 攻击可以通过转义字符“<”、“>”和“&”来缓解。例如,如果值为{'hello': 'world</script>&amp;'},则输出为:

<script id="hello-data" type="application/json">
    {"hello": "world\\u003C/script\\u003E\\u0026amp;"}
</script> 
Run Code Online (Sandbox Code Playgroud)

这与禁止页面内脚本执行的严格内容安全策略兼容。它还在被动数据和可执行代码之间保持清晰的分离。


lgu*_*iel 6

您可以在Django中使用safeescapejs内置过滤器的组合.

var json_string = unescape({{json_list | safe | escapejs}});
var json_data = JSON.parse(json_string);
Run Code Online (Sandbox Code Playgroud)