2

I'm writing a Flask app using jinja2, and I'm trying to pass my Python variables both into some Javascript and HTML. I made Javascript and HTML templates, but for some reason the Javascript is getting rendered and displayed in the wrong place, and I can't figure out what the problem is.

My controller code that passes my Python data, and renders my templates is:

@info_page.route('/info.html', methods=['GET'])

def info():
    ''' Documentation here. '''

    session = db.Session()
    infoDict = {}
    jsDict = {}

    ... 

    infoDict['character'] = character
    infoDict['name']=name
    jsDict['powertree']=powertree

    js = render_template('powertree.js', **jsDict)
    infoDict['js']=js

    return render_template("info.html", **infoDict)

The template for info.html is:

{% extends "layout.html" %}

{% block head %}
    <link rel="stylesheet" type="text/css" href="    {{url_for('static',filename='css/index.css')}}">
{% endblock head %}

{% block code %}
   {{js}}
{% endblock code %}

{% block body %}
    <h1>{{name}}</h1>
  ...
{% endblock body %}

And the template for powertree.js is:

 <script type='text/javascript'>
    $(document).ready(function() {

    var data = {{powertree}};
    console.log('hello, inside powertree');

    });
 </script>

The rendered Javascript code is just visibly printed at the top of my webpage. Looking at the DOM shows it's displayed inside the HTML body and not inside the HTML head, where it belongs. If I remove the {{js}} and replace it with the actual code inside powertree.js, everything renders fine, and works as expected. However I'd rather keep my Javascript in a separate file as it will get quite long. Why doesn't this work? How can I easily pass my variables into Javascript code so I can reference, in this example {{powertree}} in my js? Because it just visibly prints the Javascript at the top of my webpage, it makes me think it's a simple syntax error with a missing or something like that, but I can't find anything.

Thanks.

2 Answers 2

1

What happened is that for all files with filename extension .html (and a few others) certain safeties are applied, namely the filtering out of html special characters (like <, > and a few others, refer to the documentation) by converting them to the html entities equivalent. To ensure that the strings are not escaped, you want to change the rendering part to:

{% block code %}
   {{js|safe}}
{% endblock code %}

Note that you have to be sure that your code will not contain any raw user input, as that opens up XSS vulnerability.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you kind person. That did the trick. I also had to change the var data = {{powertree}} to var data = {{powertree|tojson}} to get it to work as well.
0

Another solution is to mark the js variable as being safe for inclusion directly in your python code by using the Markup class:

from jinja2 import Markup

infoDict['js']= Markup(js)

This is preferable to using the |safe filter in the template code because:

  1. you can indicate that a variable is safe at the place where it is defined; this avoids having to remember this information and can possibly prevent double escaping.
  2. in the case where templates and Python code are written separately (e.g. by two different people, or at different times), you don't need to communicate the safeness of variables to the template designer.

1 Comment

Oh ok. This makes sense as well and may ultimately be what I do. Thanks. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.