代码之家  ›  专栏  ›  技术社区  ›  Stephen

使用appengine中的图表和jinja2[副本]

  •  0
  • Stephen  · 技术社区  · 7 年前

    假设我有一个python变量:

    list_of_items = ['1','2','3','4','5']
    

    我通过呈现html将其传递给jinja,并且我还有一个javascript函数 somefunction(variable) . 我正试着把 list_of_items . 我试过这样的方法:

    {% for item in list_of_items %}
    <span onclick="somefunction({{item}})">{{item}}</span><br>
    {% endfor %}
    

    是否可以将列表从python传递到javascript,或者应该在循环中逐个传递列表中的每个项?我该怎么做?

    0 回复  |  直到 7 年前
        1
  •  84
  •   mdeous    12 年前

    要将一些上下文数据传递给javascript代码,必须以javascript(即json)可以理解的方式对其进行序列化。您还需要使用 safe Jinja过滤器,防止你的数据被篡改。

    你可以这样做:

    视图

    import json
    
    @app.route('/')
    def my_view():
        data = [1, 'foo']
        return render_template('index.html', data=json.dumps(data))
    

    模板

    <script type="text/javascript">
        function test_func(data) {
            console.log(data);
        }
        test_func({{ data|safe }})
    </script>
    

    编辑-准确答案

    因此,要实现您想要的目标(循环遍历一个项列表,并将它们传递给javascript函数),您需要分别序列化列表中的每个项。然后,您的代码将如下所示:

    视图

    import json
    
    @app.route('/')
    def my_view():
        data = [1, "foo"]
        return render_template('index.html', data=map(json.dumps, data))
    

    模板

    {% for item in data %}
        <span onclick=someFunction({{ item|safe }});>{{ item }}</span>
    {% endfor %}
    

    编辑2

    在我的例子中,我使用 Flask ,我不知道你在使用什么框架,但是你有了这个想法,你只需要让它适合你使用的框架。

    编辑3(安全警告)

    永远不要对用户提供的数据执行此操作,只能对受信任的数据执行此操作!

    否则,您的应用程序将暴露于xss漏洞!

        2
  •  24
  •   Godsmith    12 年前

    我在使用flask时遇到了类似的问题,但我不必使用json。我刚通过一个名单 letters = ['a','b','c'] 具有 render_template('show_entries.html', letters=letters) 并设置

    var letters = {{ letters|safe }}
    

    在我的javascript代码中。Jinja2替换 {{ letters }} 具有 ['a','b','c'] ,javascript将其解释为字符串数组。

        3
  •  0
  •   muratgozel    9 年前

    我可以建议您使用一种面向javascript的方法,它可以使您在项目中轻松地使用javascript文件。

    在jinja模板文件中创建一个javascript部分,并将要在javascript文件中使用的所有变量放在窗口对象中:

    小精灵

    ...
    {% block scripts %}
    <script type="text/javascript">
    window.appConfig = {
        debug: {% if env == 'development' %}true{% else %}false{% endif %},
        facebook_app_id: {{ facebook_app_id }},
        accountkit_api_version: '{{ accountkit_api_version }}',
        csrf_token: '{{ csrf_token }}'
    }
    </script>
    <script type="text/javascript" src="{{ url_for('static', filename='app.js') }}"></script>
    {% endblock %}
    

    jinja将替换值,我们的appconfig对象可以从其他脚本文件访问:

    App.JS

    var AccountKit_OnInteractive = function(){
        AccountKit.init({
            appId: appConfig.facebook_app_id,
            debug: appConfig.debug,
            state: appConfig.csrf_token,
            version: appConfig.accountkit_api_version
        })
    }
    

    我已经用这种更容易管理和搜索引擎友好的方式将javascript代码从html文档中分离出来。

        4
  •  0
  •   Sylhare    8 年前

    为了总结选择的答案,我一直在使用Jinja2和Flask测试一个新的选项:

    @app.route('/')
    def my_view():
        data = [1, 2, 3, 4, 5]
        return render_template('index.html', data=data)
    

    模板:

    <script>
        console.log( {{ data | tojson }} )
    </script>
    

    渲染模板的输出:

    <script>
        console.log( [1, 2, 3, 4] )
    </script>
    

    这个 safe 可以添加,但是 {{ data | tojson | safe }} 但它也在发挥作用。

        5
  •  0
  •   Mark Amery Harley Holcombe    7 年前

    你可以用Jinja的 tojson 过滤器,它

    将结构转储为json,以便在中安全使用 <script> 标记[和]在HTML中的任何位置,但双引号属性除外。

    例如,在python中,编写:

    some_template.render(list_of_items=list_of_items)
    

    …或者,在烧瓶端点的上下文中:

    return render_template('your_template.html', list_of_items=list_of_items)
    

    然后在模板中,编写以下内容:

    {% for item in list_of_items %}
    <span onclick='somefunction({{item | tojson}})'>{{item}}</span><br>
    {% endfor %}
    

    (注意 onclick 属性是 单一的 -引用。这是必要的,因为 |tojson 逃逸 ' 角色但不是 " 其输出中的字符,这意味着它可以安全地用于单引号的HTML属性,但不能用于双引号的HTML属性。)

    或使用 list_of_items 在内联脚本而不是html属性中,编写以下内容:

    <script>
    const jsArrayOfItems = {{list_of_items | tojson}};
    // ... do something with jsArrayOfItems in JavaScript ...
    </script>
    

    不要使用 json.dumps 对python代码中的变量进行json编码,并将生成的json文本传递给模板。这将对某些字符串值产生不正确的输出,如果您试图对用户提供的值进行编码,则会将您暴露给xss。这是因为python的内置 JSON转储 不能转义为 < > (需要转义才能将值安全地模板化到内联 <脚本& GT; S,如在 https://html.spec.whatwg.org/multipage/scripting.html#restrictions-for-contents-of-script-elements )或单引号(需要转义以将模板值安全地转换为单引号的html属性)。

    如果你用的是烧瓶,请注意烧瓶注入的是 tojson 过滤而不是使用Jinja的版本。然而,上面写的一切仍然适用。这两个版本的行为几乎完全相同;Flask只是 allows for some app-specific configuration 在Jinja的版本中没有。