简体   繁体   中英

Javascript not rendering correctly in Flask jinja2 templates

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.

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.

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 (eg by two different people, or at different times), you don't need to communicate the safeness of variables to the template designer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM