Django模板 - 将Python列表转换为JavaScript对象
我正在做一个Django/Python的网站。我有一个页面,想在上面显示搜索结果的表格。结果列表是正常传递到模板中的。
我还想让这个对象列表可以被JavaScript代码访问。
我最开始的解决办法是创建另一个视图,返回JSON格式的数据。但每次加载页面都需要查询两次,这样就不太方便了。于是我尝试只用JSON视图下载数据,然后用JavaScript来打印表格。
但这样也不太好,因为现在展示的内容和JavaScript代码混在一起了。
有没有办法在页面渲染的时候,把Python列表转换成JavaScript对象呢?
4 个回答
怎么样,有没有一种过滤器可以把Python的值转换成JSON格式?这里有一个简单的实现示例:
http://djangosnippets.org/snippets/201/
因为JSON的值恰好也可以用在JavaScript的赋值操作中,所以你可以直接在你的脚本里放一些像这样的内容...
var results = {{results|jsonify}};
。
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>
这样的字符串也不会出问题。
解决方案
我创建了一个自定义模板过滤器,具体可以参考 自定义模板标签和过滤器。
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)