从Flask传递变量到JavaScript

41

我查看了类似的论坛,但无法获得任何解决方案。我正在尝试从Flask将变量传递到我的JavaScript文件中。这些值将在我的JavaScript文件中用于PubNub。

以下是我的Python代码的一部分:

@app.route("/mysettings/")
def user_settings(): 
        return render_template('Settings.html',  project_name = session['project_name'] , publish_key = session['publish_key'] , subscribe_key = session['subscribe_key'] )

这是我的 JavaScript 代码的一部分(app.js):

var settings = {
        channel: {{project_name}},
        publish_key: {{publish_key}},
        subscribe_key: {{subscribe_key}}
    };

如果我在我的Settings.html文件中使用它,这段代码可以工作,但是在app.js文件中就不行。

5个回答

51

mobiusklein的回答相当不错,但是你应该考虑一下“hack”方法。定义你的Javascript方法以接收参数,并将数据作为参数发送到函数中。

main.py

@app.route('/')
def hello():
    data = {'username': 'Pang', 'site': 'stackoverflow.com'}
    return render_template('settings.html', data=data)

app.js

function myFunc(vars) {
    return vars
}

settings.html

<html>
    <head>
         <script type="text/javascript" {{ url_for('static', filename='app.js')}}></script>
         <script type="text/javascript">
            myVar = myFunc({{data|tojson}})
         </script>
    </head>
</html>

4
在我看来,这很正常,不是黑客攻击。 - Alex Hall
3
vars/tojson:这个函数救了我这个非Web开发者的命 :D,谢谢。 - Oxydron
1
@MauroBaraldi 不,我有一个用于翻译字典的@context_processor,并且需要链接一些单独的js文件,并在该文件中使用{{translations.somevar|tojson}},这是否可行? - Beqa Bukhradze
19
你的意思是 {{data|tojson}},应该这样翻译。 - Bob Stein
2
FYI - tojson和其他过滤器的文档:https://jinja.palletsprojects.com/en/2.11.x/templates/#builtin-filters - s2t2
显示剩余10条评论

37

使用 @mauro 提供的简单示例,从 Flask 视图传递变量到模板,再传递到 JavaScript 文件的简单方法。

main.py

@app.route('/')
def hello():
    data = {'username': 'Pang', 'site': 'stackoverflow.com'}
    return render_template('settings.html', data=data)

设置.html

<html>
    <head>
         <script type="text/javascript">
            var username = {{ data.username }}
            var site = {{ data.site }}
        </script>
        <script type="text/javascript" src="app.js"></script>
    </head>
</html>

app.js

function myFunc() {
    return username + site
}

7
只有在我将 data.username 更改为 data.username|tojson 后,这个答案才适用于我(如果名称中包含斜杠,例如 "/example/name",则会传递变量)。 - Sam
请按照@joash的答案为变量分配flask变量。 - R.S.K

12
<script type="text/javascript">
   var username ='{{ data.username }}'
   var site ='{{ data.site}}'
<script>

2
这个很好用,但是在vscode中,javascript检查器会因为jinja的花括号而发出警告。为了抑制这些警告,我在我的settings.json文件中添加了以下内容:"html.validate.scripts": false。这将抑制对HTML文件中JavaScript语法的检查。 - yomajo

7

造成这种情况的原因是需要使用jinja2进行替换,而从您的代码中看不出来这一点。

很可能您正在将app.js作为静态文件进行服务,这意味着模板引擎机制根本不会对其进行处理,只是直接原样提供。

您可以通过从与操作相关联的URL中提供app.js来实现所描述的内容,该操作将通过Flask的render_template函数传递app.js的内容,执行jinja2替换以及所有其他自定义信息,但这意味着jinja2必须解析整个文件,这可能代价高昂。

您可以尝试使用AJAX请求来传递这些变量,由一个操作响应并以JSON形式发送相同数据。这是一种更常见的做法,并且具有使该数据可见于其他资源的附加价值。


0
在这种情况下,您实际上不需要使用render_template()发送数据,因为您的数据已经存储在会话中。您的会话数据已经可以在jinja2模板中使用。(您可能无法从app.js导入它。您可能需要在“Settings.html”中显式包含所有代码。)

main.py

@app.route("/mysettings/")
def user_settings(): 
    return render_template('Settings.html')

settings.html

<script type="text/javascript">
var settings = {
    channel: {{ session.project_name }},
    publish_key: {{ session.publish_key }},
    subscribe_key: {{ session.subscribe_key }}
};
</script>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接