7

If I'd like to generate JavaScript code, and not just HTML, through Jinja2, am I stuck with keeping the JS code inline, or is there a way for me to reference the script?

Concretely:

app.py

from flask import Flask, render_template
app = Flask(__name__)
app.config['DEBUG'] = True

@app.route('/')
def index():
    return render_template('index.html', name='Sebastian', color='pink')

if __name__ == '__main__':
    app.run()

index.html

<!DOCTYPE html>
<html>
    <head>
        <meta content="utf-8" http-equiv="encoding">
        <script>
            function myEnterFunction() {
                element = document.getElementById("demo");
                element.style.backgroundColor = "{{ color }}";
            }
        </script>
    </head>
    <body>
        <p>Hello {{ name }}</p>
        <div onmouseenter="myEnterFunction()">
            <p>onmouseenter:
                <span id="demo">Mouse over me!</span>
            </p>
        </div>
    </body>
</html>

This works fine if the JavaScript code is inlined, but what if we'd like to remain tidy and reference a separate file?

<head>
    <meta content="utf-8" http-equiv="encoding">
    <script src="code.js"></script>
</head>

?

Possibly, this can be done by replacing src="code.js" with

{% render_template('code.js', color=color) %}

Can you see how to render a JS template while you're rendering an HTML template?

Calaf
  • 10,113
  • 15
  • 57
  • 120
  • Possible duplicate of [Use Jinja2 template engine in external javascript file](http://stackoverflow.com/questions/21956500/use-jinja2-template-engine-in-external-javascript-file) – Mike Cluck Jul 11 '16 at 20:18
  • You're right. The question is similar. But the preferred answer there is not suitable because the question is overly simple. Here also the code is simplified for clarity. The reason why the alternative answer there "*is probably not a very good idea*" is not stated (nor clear to me). The answer here is just right. – Calaf Jul 11 '16 at 20:28

1 Answers1

13

You can add a route that generates the JS.

@app.route('/script.js')
def script():
    return render_template('script.js', color='pink')

And in script.js, this should be in the same folder as your other templates:

 function myEnterFunction() {
                element = document.getElementById("demo");
                element.style.backgroundColor = "{{ color }}";
            }

And in your layout.html:

<script src="{{url_for('script')}}"></script>

Jinja2 will parse any files containing it's syntax.

Sinan Guclu
  • 1,075
  • 6
  • 16
  • Works fine tho... @Sinan Guclu, what if you want to keep the js file in the `static` folder, how do you reference it in `render_template()` ? – Young Emil Mar 02 '18 at 10:36
  • And is it possible? – Young Emil Mar 02 '18 at 10:37
  • @YoungMillie While is is possible using `render_template_string`, it wouldn't make much sense unless you just had one set of python variables that you wanted to be rendered into all of the static files. There is an example implementation [on this Gist](https://gist.github.com/Driptap/25ba392b00c8b0e0dfe88c7b8c180ca7) – Sinan Guclu Mar 03 '18 at 14:00