Django模板 - 将Python列表转换为JavaScript对象

23 投票
4 回答
32612 浏览
提问于 2025-04-16 10:00

我正在做一个Django/Python的网站。我有一个页面,想在上面显示搜索结果的表格。结果列表是正常传递到模板中的。

我还想让这个对象列表可以被JavaScript代码访问。

我最开始的解决办法是创建另一个视图,返回JSON格式的数据。但每次加载页面都需要查询两次,这样就不太方便了。于是我尝试只用JSON视图下载数据,然后用JavaScript来打印表格。

但这样也不太好,因为现在展示的内容和JavaScript代码混在一起了。

有没有办法在页面渲染的时候,把Python列表转换成JavaScript对象呢?

4 个回答

23

怎么样,有没有一种过滤器可以把Python的值转换成JSON格式?这里有一个简单的实现示例:

http://djangosnippets.org/snippets/201/

因为JSON的值恰好也可以用在JavaScript的赋值操作中,所以你可以直接在你的脚本里放一些像这样的内容...

var results = {{results|jsonify}};

25

Django 2.1 新特性: json_script

Django 2.1 新增了一个模板标签:json_script。这个标签几乎正是你需要的,甚至可能更好。它可以把 Python 的值转换成 JSON 格式,并且用一个 <script> 标签包裹起来。所以这个模板:

{{ value|json_script:"foobar" }}

... 会生成这个:

<script id="foobar" type="application/json">{"example": "example"}</script>

这不是一个普通的 Javascript <script> 标签,它不会执行任何代码,只是简单的 JSON 数据。如果你想在 Javascript 中访问这些内容,可以这样做:

var value = JSON.parse(document.getElementById('foobar').textContent);

这个标签的设计确保了内容是安全的,比如里面有 </script> 这样的字符串也不会出问题。

25

解决方案

我创建了一个自定义模板过滤器,具体可以参考 自定义模板标签和过滤器

from django.core.serializers import serialize
from django.db.models.query import QuerySet
from django.utils import simplejson
from django.utils.safestring import mark_safe
from django.template import Library

register = Library()

def jsonify(object):
    if isinstance(object, QuerySet):
        return mark_safe(serialize('json', object))
    return mark_safe(simplejson.dumps(object))

register.filter('jsonify', jsonify)
jsonify.is_safe = True   

调用 mark_safe 是很重要的。否则,Django 会对内容进行转义处理。

在模板中:

//Without template filter (you'll need to serialise in the view)
var data = jQuery.parseJSON('{{ json_data|safe }}');
alert(data.length);

//Using the template filter    
var data2 = jQuery.parseJSON('{{ record_list|jsonify }}');
alert(data2.length);

注意模板标签周围的单引号。

不过我下一个想问的问题是 - 这真的安全吗?

更新

这是一个更新版本,适用于 Django 1.8 的上述模板标签,它还可以处理传入的扁平值列表,比如 values_list('myfield', flat=True):

from django.core.serializers import serialize
from django.db.models.query import QuerySet, ValuesListQuerySet
from django.template import Library

import json

register = Library()

@register.filter( is_safe=True )
def jsonify(object):

    if isinstance(object, ValuesListQuerySet):
        return json.dumps(list(object))
    if isinstance(object, QuerySet):
        return serialize('json', object)
    return json.dumps(object)

撰写回答