Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jinja render text in HTML preserving line breaks

Tags:

I have a simple form like this:

class RecordForm(Form):         notes = TextAreaField('Notes') 

I record the data in three paragraphs like this:

para1  para2  para3 

In the template I would like to see the content of that record in read-only. (Not editable form)

record is this case the model containing the data:

<td>{{ record.notes }}</td> 

-->

<td>para1 para2 para3</td> 

What can I do to make it to show the multi-lines?

like image 404
Houman Avatar asked Sep 06 '13 17:09

Houman


People also ask

Does Jinja escape HTML?

Jinja provides a feature that can be enabled to escape HTML syntax in rendered templates. However, it is disabled by default. Jinja is a general purpose template engine, it is not only used for HTML documents. You can generate plain text, LaTeX, emails, CSS, JavaScript, configuration files, etc.

Can I use Jinja in HTML?

Jinja can generate any text-based format (HTML, XML, CSV, LaTeX, etc.). A Jinja template doesn't need to have a specific extension: . html , . xml , or any other extension is just fine.

What is the difference between Jinja and Jinja2?

from_string . Jinja 2 provides a Template class that can be used to do the same, but with optional additional configuration. Jinja 1 performed automatic conversion of bytes in a given encoding into unicode objects.

How do you get rid of whitespace in Jinja?

You do it by using a minus sing - to strip whitespaces from blocks, comments or variable expressions. You need to add it to the start or end of given expression to remove whitespaces before or after the block, respectively.


2 Answers

All whitespace, including newlines, is turned into a single space in HTML.

Your options, from best to worst:

  1. Put white-space: pre-wrap; on the containing element. This tells HTML to show all whitespace exactly as it appears in the source, including newlines. (You could also use a <pre> tag, but that will also disable word-wrapping, which you probably don't want.)
  2. Treat the plain text as Markdown and throw a Markdown processor at it—one of the things Markdown does is wrap paragraphs in <p>.
  3. In Python-land, do .replace('\n', '<br>'). But this leaves you vulnerable to XSS because there might be other HTML-like junk in the string, and fixing that is a bit of a pain.
like image 84
Eevee Avatar answered Sep 24 '22 07:09

Eevee


As suggested by Martijn Pieters (by linking Flask snippet 28), there is also the possibility to add a custom filter for that. The link is outdated, because Flask Snippets are no longer provided.

So I will provide the snippet from web archive here:

nl2br filter

Posted by Dan Jacob on 2010-06-17 @ 05:03 and filed in Template Tricks

This is a nl2br (newline to <BR>) filter, adapted from the Jinja2 example here:

http://jinja.pocoo.org/2/documentation/api#custom-filters

import re  from jinja2 import evalcontextfilter, Markup, escape  _paragraph_re = re.compile(r'(?:\r\n|\r|\n){2,}')  app = Flask(__name__)  @app.template_filter() @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 

The link above about custom-filters seems to be outdated, too. Here is a similar link from the current stable version 1.1: https://flask.palletsprojects.com/en/1.1.x/templating/#registering-filters

I'm not really sure why he uses such a complicated result computation. For me the following code worked and it's much simpler. Maybe, the variant above is better if you don't use autoescape (which I do not want to disable)?! Anyway, now both variants are available:

# custom_template_filters.py  from flask import Blueprint from jinja2 import evalcontextfilter, Markup, escape  blueprint = Blueprint('custom_template_filters', __name__)  @evalcontextfilter @blueprint.app_template_filter() def newline_to_br(context, value: str) -> str:     result = "<br />".join(re.split(r'(?:\r\n|\r|\n){2,}', escape(value)))      if context.autoescape:         result = Markup(result)      return result 

It is worth mentioning that the code snippet from Dan Jacob uses Python2, and I get the template filters running via Blueprint. For the sake of completeness I also provide the app.py using a factory method:

# app.py  from flask import Flask  def create_app() -> Flask:     app = Flask(__name__)     ...     register_template_filters(flask_app=app)     return app  def register_template_filters(flask_app: Flask) -> None:     from . import custom_template_filters     flask_app.register_blueprint(custom_template_filters.blueprint)     return None 

It is more or less an implementation detail how you will get the context filter working. The main idea is inside the function nlbr or newline_to_br itself. If you get the custom filter working, it is available in all your Jinja templates and you can use it like this:

{{ anystring | newline_to_br }} 
like image 29
colidyre Avatar answered Sep 23 '22 07:09

colidyre