Passing HTML to template using Flask/Jinja2

I’m building an admin for Flask and SQLAlchemy, and I want to pass the HTML for the different inputs to my view using render_template. The templating framework seems to escape the HTML automatically, so all <"'> characters are converted to HTML entities. How can I disable that so that the HTML renders correctly?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

To turn off autoescaping when rendering a value, use the |safe filter.

{{ something|safe }}

Only do this on data you trust, since rendering untrusted data without escaping is a cross-site scripting vulnerability.

Method 2

MarkupSafe provides Jinja’s autoescaping behavior. You can import Markup and use it to declare a value HTML safe from the code:

from markupsafe import Markup
value = Markup('<strong>The HTML String</strong>')

Pass that to the templates and you don’t have to use the |safe filter on it.

Method 3

From the Jinja docs section HTML Escaping:

When automatic escaping is enabled everything is escaped by default
except for values explicitly marked as safe. Those can either be
marked by the application or in the template by using the |safe
filter.

Example:

 <div class="info">
   {{data.email_content|safe}}
 </div>

Method 4

When you have a lot of variables that don’t need escaping, you can use an autoescape override block:

{% autoescape false %}
{{ something }}
{{ something_else }}
<b>{{ something_important }}</b>
{% endautoescape %}

Method 5

Some people seem to turn autoescape off which carries security risks to manipulate the string display.

If you only want to insert some linebreaks into a string and convert the linebreaks into <br />, then you could take a jinja macro like:

{% macro linebreaks_for_string( the_string ) -%}
{% if the_string %}
{% for line in the_string.split('n') %}
<br />
{{ line }}
{% endfor %}
{% else %}
{{ the_string }}
{% endif %}
{%- endmacro %}

and in your template just call this with

{{ linebreaks_for_string( my_string_in_a_variable ) }}

Method 6

For handling line-breaks specifically, I tried a number of options before finally settling for this:

{% set list1 = data.split('n') %}
{% for item in list1 %}
{{ item }}
  {% if not loop.last %}
  <br/>
  {% endif %}
{% endfor %}

The nice thing about this approach is that it’s compatible with the auto-escaping, leaving everything nice and safe. It can also be combined with filters, like urlize.

Of course it’s similar to Helge’s answer, but doesn’t need a macro (relying instead on Jinja’s built-in split function) and also doesn’t add an unnecesssary <br/> after the last item.

Method 7

Use the safe filter in your template, and then sanitize the HTML with the bleach library in your view. Using bleach, you can whitelist the HTML tags that you need to use.

This is the safest, as far as I know. I tried both the safe filter and the Markup class, and both ways allowed me to execute unwanted JavaScript. Not very safe!


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x