Welcome | Get started | Dive | Contribute | Topics | Reference | Changes | More
Generating HTML¶
Although Lino is made to avoid writing HTML, CSS and JavaScript, there are cases where even the most design-agnostic application developer is asked to provide some “rich” (“formatted”) text. And the most natural and best known language for writing rich text remains HTML.
For example the return value of a DisplayField
or a HtmlBox
, or the get_table_summary
method are places where the
application developer is expected to write “rich text” that contains formatting,
hyperlinks, widgets.
But how to generate HTML from application code?
You might ask “Where’s the problem?” Python is a great language for generating HTML, you just do it. For example:
class Message:
title = "Invitation"
name = "Joe"
def as_html(self):
return f"<h1>{self.title}</h1><p>Hello, {self.name}!</p>"
p = Message()
print(p.as_html())
The problem in above example is that it forgets to escape the title and
name. If a title or name contains HTML special characters like <
or
&
, they might not get rendered correctly.
Another problem is that a valid HTML text can get escaped by mistake, because of a bug or some API change.
The problem with these problems is that they can be difficult to track and to fix.
Lino exposes two different approaches for handling these challenges: The ElementTree module of the Standard Library and Django’s safestring tools.
Both approaches introduce some kind of “discipline”: their usage requires a bit of additional learning, but as a reward they increase stability of your code.
With ElementTree, the above example becomes:
from lino.utils.html import E, tostring
class Message:
title = "Invitation"
name = "Joe"
def as_html(self):
return [E.h1(self.title), E.p(f"Hello, {self.name}!")]
p = Message()
print(tostring(p.as_html()))
See etgen for more information about this approach.
With Django’s safestring
tools it becomes:
from django.utils.html import format_html
class Message:
title = "Invitation"
name = "Joe"
def as_html(self):
return format_html("<h1>{}</h1><p>Hello, {}!</p>", self.title, self.name)
p = Message()
print(p.as_html())
As a Lino application developer you should get used to both approaches.