gsgx
gsgx

Reputation: 12249

Allowing <br> tags with Google App Engine and Jinja2

In my web app, the user can make blog posts. When I display the blog post, newlines aren't shown because I didn't replace the new lines with <br> tags. The problem is that I've turned autoescaping on in Jinja, so <br> tags are escaped. I don't want to temporarily disable autoescaping, I want to specifically allow <br> tags. How would I do this?

Upvotes: 10

Views: 5305

Answers (8)

sqram
sqram

Reputation: 7201

Note that i have autoescape on by default, so I don't check it in this function, but this is what I'm using

def nl2br(value): 
  split = value.split('\n')
  return jinja2.Markup('<br>').join(split)

then of course,

jinja_env.filters['nl2br'] = nl2br

Upvotes: 0

Qi Ge
Qi Ge

Reputation: 27

Here's a filter wrote by myself:

import jinja2

@jinja2.evalcontextfilter
def nl2br(eval_ctx, value):
    result = jinja2.escape(value).unescape().replace('\n', '<br>')
    if eval_ctx.autoescape:
        result = jinja2.Markup(result)
    return result

And add the filter to the jinja2.Environment() by calling:

jinja_env.filters['nl2br'] = nl2br

Upvotes: 0

Hern&#225;n Acosta
Hern&#225;n Acosta

Reputation: 695

You can create a jinja2 filter:

import re
from jinja2 import evalcontextfilter, Markup, escape

_paragraph_re = re.compile(r'(?:\r\n|\r|\n){2,}')

@evalcontextfilter
def nl2br(eval_ctx, value):
    result = u'\n\n'.join(u'<p>%s</p>' % p.replace('\n', '<br>\n')
                          for p in _paragraph_re.split(escape(value)))
    if eval_ctx.autoescape:
        result = Markup(result)
    return result

You need to add the filter to your jinja2 Environment before you can use it:

JINJA2_ENV.filters['nl2br'] = jinja2_filters.nl2br

In your template you can use that filter:

{{post.content|nl2br}}

Upvotes: 0

gsgx
gsgx

Reputation: 12249

I have another answer that I think is the best. Initially I was just displaying my variable post.content as-is, and the newlines weren't being preserved. None of the solutions here worked (well), and my pre solution was just a quick fix and had major issues. This is the real solution:

{% for line in post.content.splitlines() %}
    {{line}}<br>
{% endfor %}

Upvotes: 29

thakis
thakis

Reputation: 5909

In your model object, add a function like this:

class Post(db.Model):
    # ...

    def html_content(self):
        # Escape, then convert newlines to br tags, then wrap with Markup object
        # so that the <br> tags don't get escaped.
        def escape(s):
            # unicode() forces the conversion to happen immediately,
            # instead of at substitution time (else <br> would get escaped too)
            return unicode(jinja2.escape(s))
        return jinja2.Markup(escape(self.content).replace('\n', '<br>'))

Then in your template, just call that:

<p>{{ post.html_content() }}</p>

Upvotes: 2

dav1d
dav1d

Reputation: 6055

You can use the |safe filter, or use the autoescape blocks:

{% autoescape false %}
{{ content goes here }}
{% autoescape %}

You could also set autoescaping in the environment to False.

Upvotes: 2

Nick Johnson
Nick Johnson

Reputation: 101149

The easiest way to do this is to escape the field yourself, then add line breaks. When you pass it in in jinja, mark it as safe so it's not autoescaped.

Upvotes: -1

gsgx
gsgx

Reputation: 12249

The solution was to put <pre></pre> tags around the area where I had the content.

Upvotes: -1

Related Questions