Passing variables from Flask to JavaScript
Asked Answered
S

5

42

I looked at similar forums but was not able to get any of the solutions to work. I am trying to pass variables from Flask to my JavaScript file. These values then will be used for PubNub from my JavaScript file.

Here is part of my Python code:

@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'] )

Here is part of my JavaScript code (app.js):

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

this code works if I use it in my Settings.html file but not in the app.js file.

Sinful answered 16/5, 2016 at 17:28 Comment(0)
G
52

The mobiusklein answers is pretty good, but there is "hack" you should consider. Define your Javascript method to receive params and send data as params to your function.

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>
Guidon answered 16/5, 2016 at 18:11 Comment(15)
This seems normal to me, not a hack.Raymundorayna
vars/tojson: this saved my life as non-web developer :D ThanksUncounted
I need different answer, how can I pass {{translations.somevar }} dict to js file ?Novokuznetsk
@BeqaBukhradze same way {{translations.somevar|tojson}}Guidon
@MauroBaraldi nope, I have @ context_processor for translations dictionary and need to link some js separate file and in that file need to use {{translations.somevar|tojson}} and is that possible ?Novokuznetsk
Well, so you need to process this JS file aside, then use it.Guidon
@MauroBaraldi Yes and does jinja will guess my dict variables with {{translations.somevar|tojson}} ?Novokuznetsk
#32879156Novokuznetsk
@BeqaBukhradze the point is, it will work if your JS code were embedded in HTML code. If it is in another file no.Guidon
@MauroBaraldi Yes I need to use it in separate fileNovokuznetsk
@BeqaBukhradze I answered that questionGuidon
Think you meant {{data|tojson}}.Tautog
FYI - Docs for tojson and other filters: jinja.palletsprojects.com/en/2.11.x/templates/#builtin-filtersTransudate
This works initially; but how can one repeatedly call JavaScript with updated context? My JS function is only called on the first GET request/render of the template. Then I want to update the context, and call that JS function in a loop, accepting updated context, without waiting for requestsHunkers
@Hunkers it should work, because it is not a Flask issue, but a JS issue. You could call the request as you want (or your server can handle), from the backend side.Guidon
S
38

Simple way to pass variables from flask view to template to javascript file with simple example mentioned by @mauro.

main.py

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

settings.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
}
Sandhi answered 28/7, 2017 at 12:21 Comment(2)
This answer worked for me only after I changed data.username to data.username|tojson (I'm passing variable whose name contains slashes, e.g. "/example/name" if that matters.)Irk
Follow @joash answer below for the variables should be assigned the flask variableBoughton
P
13
<script type="text/javascript">
   const username = "{{ data.username }}";
   const site = "{{ data.site }}";
</script>
Pyromania answered 5/3, 2020 at 15:24 Comment(1)
This works well, but on vscode javascript checker will get angry about jinja's curly brackets. To suppress the warnings I added this to my settings.json:"html.validate.scripts": false, This suppresses javascript syntax checking on html files.Childish
G
7

The reason is that jinja2 needs to be used to perform the substitution, which from your code doesn't appear to be happening.

Chances are you're serving app.js as a static file, which means that it is never looked at by the templating engine machinery, just served as is.

You can accomplish what you're describing by serving app.js from a URL which is tied to an action which passes the contents of app.js through Flask's render_template function, performing jinja2 substitutions, and all the other customization information, but that means jinja2 has to parse the whole file, which can be expensive.

You might try to pass those variables along using an AJAX request responded to by an action that sends back that same data in JSON. This is a much more common practice, and has the added value of making that data visible to other resources.

Godsend answered 16/5, 2016 at 17:43 Comment(0)
B
0

In this instance, you don't actually need to send your data with render_template() because your data is already stored in your session. Your session data is already available to a jinja2 template. (You might not be able to import it from app.js. You might need to include all the code explicitly in '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>
Barcarole answered 17/7, 2022 at 19:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.