【问题标题】:Django Template - Convert a Python list into a JavaScript objectDjango 模板 - 将 Python 列表转换为 JavaScript 对象
【发布时间】:2011-06-09 13:15:30
【问题描述】:

我正在开发一个 Django / Python 网站。我有一个页面,我想在其中显示搜索结果表。结果列表照常传递给模板。

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

我的第一个解决方案是创建另一个返回 JSON 格式的视图。但是每个页面加载都需要调用两次查询。所以我尝试只使用 JSON 视图下载数据并使用 JavaScript 打印表格。

但这也是不可取的,因为现在表示层已混入 JavaScript 代码中。

有没有办法在页面呈现时从 Python 列表创建一个 JavaScript 对象?

【问题讨论】:

    标签: javascript python django django-templates


    【解决方案1】:

    将 Python 值转储到 JSON 的过滤器怎么样?这是一个示例实现:

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

    由于 JSON 值也恰好是 Javascript 赋值的有效右侧,因此您可以简单地放置类似...

    var results = {{results|jsonify}};
    

    在您的脚本中。

    【讨论】:

    • 有效!您可能还需要在 appname/templatetags/ 目录中添加一个空白的 init.py 文件
    【解决方案2】:

    解决方案

    我创建了一个自定义模板过滤器,请参阅custom template tags and filters

    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)
    

    【讨论】:

    • 也许我们可以用{{ record_list|jsonify|safe }}代替{{ record_list|jsonify }} + mark_safe(), ...
    • ValuesListQuerySet 已在 django >1.9 的更高版本中删除。 Values_list 被告知是另一种选择。但是您能否帮助更新此解决方案本身。
    【解决方案3】:

    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 &lt;script&gt; 标签,它不运行,它只是 JSON。如果你想访问 Javascript 中的内容,你可以这样做:

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

    这个标签已经被编码,所以它被正确地转义了,一个带有&lt;/script&gt;的字符串不会破坏任何东西,例如。

    【讨论】:

    • 当 Python 对象是 QuerySet 时,这似乎不起作用:QuerySet 类型的对象不是 JSON 可序列化的
    【解决方案4】:

    也看this answer

    但这不是高负载方式。你必须:

    a) 创建 JSON 文件,放置到磁盘或 S3。万一是 JSON 静态的

    b) 如果 JSON 是动态的。在您的应用程序中的单独 url(如 API)上生成 JSON。

    而且,在任何情况下都直接由 JS 加载。例如:

    $.ajax('/get_json_file.json')

    P.S.:对不起我的英语。

    【讨论】:

      猜你喜欢
      • 2021-10-01
      • 2016-08-26
      • 1970-01-01
      • 2022-11-26
      • 1970-01-01
      • 2020-07-14
      • 1970-01-01
      • 2020-09-23
      相关资源
      最近更新 更多