简体   繁体   中英

Jinja2 not rendering quotes or amp in javascript/html; safe filter not solving

First post; I will try to keep this short and sweet.

I am trying to render an edit form that detects and populates input fields if values already exist for those fields. I'm using flask with jinja2 and when I use the {{ }} print operator, my fields have their double quotes and ampersands rendered as " and & respectively.

The catch: this only happens when the print operator is being used in a javascript function. I've looked all over for solutions, and it seemed like the jinja2 safe filter would do the trick, but when I appended it to the print value, it invalidated all of my javascript.

Below is a code sample:

function test() {
    var nameField=document.getElementById("thing");
    nameField.value="{{ values[0] }}";
}

'values' is a python list.

Please let me know if I can add anything to clarify the issue.

The safe filter actually does prevent HTML escaping and thus would provide a solution to your problem.

However you get an error in JavaScript because you now have double-quotes inside a string limited by double-quotes!

Suppose the value of values[0] is the string: double-quote " and ampersand , you would get:

function test() {
    var nameField=document.getElementById("thing");
    nameField.value="double-quote " and ampersand"; //trailing and ampersand causing error
}

You can be tempted to fix the problem by replacing "{{ values[0] }}" by a single-quote wrapped string '{{ values[0] }}' . But what if your string contains single quotes?

You might also think that you will need to escape the special characters, but you would need to use java script escaping (double-quotes become %22 ) not python escaping (double-quotes become \\" ).

IMHO, the core of your problem lies in the fact that you are using Jinja to print code (not values or mark-up). When you need dynamic behavior, why change the JavaScript code when you can have a static code that provides the dynamic behavior client-side?

If values[0] is already in the DOM in your HTML file (in the id of a HTML element, or in any other attribute or in the HTML of an option of a select input), let JavaScript go and fetch it. If it is not in the DOM, put it in a hidden element with an appropriate id eg

`<div style="diplay:none;" id="value0">{{ value[0] }}</div>`  

and retrieve it when needed.

This also has the advantage of decoupling completely your JavaScript code from your server-side page generation and Jinja: your JavaScript would still work under the single condition that the correct HTML structure is provided. You would be able to move the JavaScript to a .js file and use it with other projects, as well as with projects not using Flask/Jinja2.

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