artless-template
![PyPI - License](https://img.shields.io/pypi/l/artless-template)
The artless and small template library for server-side rendering.
Artless-template allows to generate HTML, using template files or/and natively Python objects. The library encourages approaches like HTMX and No-JS.
Main principles:
- Artless, fast and small (less than 200 LOC) single-file module.
- No third party dependencies (standart library only).
- Support only modern versions of Python (>=3.10).
- Mostly pure functions without side effects.
- Interfaces with type annotations.
- Comprehensive documentation with examples of use.
- Full test coverage.
Table of Contents:
Install
$ pip install artless-template
Usage
Basically, you can create any tag with any name, attributes, text and child tags:
from artless_template import Tag as t
div = t("div")
print(div)
<div></div>
div = t("div", {"class": "some-class"}, "Some text")
print(div)
<div class="some-class">Some text</div>
div = t("div", {"class": "some-class"}, "Div text", [t("span", "Span 1 text"), t("span", "Span 2 text")])
print(div)
<div class="some-class"><span>Span 1 text</span><span>Span 2 text</span>Div text</div>
button = t("button", {"onclick": "function() {alert('hello');}"}, "Say Hello")
print(button)
<button onclick="function() {alert('hello');}">Say Hello</button>
Template and tags usage
Create templates/index.html
with contents:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>@title</title>
</head>
<body>
<main>
<section>
<h1>@header</h1>
<table>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Admin</th>
</tr>
</thead>
@users
</table>
</section>
</main>
</body>
</html>
from typing import final
from pathlib import Path
from random import randint
from dataclasses import dataclass
from artless_template import read_template, Tag as t
TEMPLATES_DIR: Path = Path(__file__).resolve().parent / "templates"
@final
@dataclass(frozen=True, slots=True, kw_only=True)
class UserModel:
name: str
email: str
is_admin: bool
users = [
UserModel(
name=f"User_{_}", email=f"user_{_}@gmail.com", is_admin=bool(randint(0, 1))
)
for _ in range(10_000)
]
users_markup = t(
"tbody",
children=[
t(
"tr",
[
t("td", user.name),
t("td", user.email),
t("td", "+" if user.is_admin else "-"),
],
)
for user in users
],
)
context = {
"title": "Artless-template example",
"header": "Users list",
"users": users_markup,
}
template = read_template(TEMPLATES_DIR / "index.html").render(**context)
Template and components usage
<!DOCTYPE html>
<html lang="en">
...
<body>
<main>
@main
</main>
</body>
</html>
from artless_template import read_template, Component, Tag as t
...
class UsersTableComponent:
def __init__(self, count: int):
self.users = [
UserModel(
name=f"User_{_}", email=f"user_{_}@gmail.com", is_admin=bool(randint(0, 1))
)
for _ in range(count)
]
def view(self):
return t(
"table",
[
t(
"thead",
[
t(
"tr",
[
t("th", "Name"),
t("th", "Email"),
t("th", "Admin"),
]
)
]
),
t(
"tbody",
[
t(
"tr",
[
t("td", user.name),
t("td", user.email),
t("td", "+" if user.is_admin else "-"),
],
)
for user in self.users
]
)
]
)
template = read_template(TEMPLATES_DIR / "index.html").render(main=UsersTableComponent(100500))
Asynchronous functions
The library provides async version of io-bound function - read_template
. An asynchronous function has a
prefix and called aread_template
.
from artless_template import aread_template
template = await aread_template("some_template.html")
...
Read detailed reference documentation.
Performance
Performance comparison of the most popular template engines and artless-template library.
The benchmark render a HTML document with table of 10 thousand user models.
Run benchmark:
$ python -m bemchmarks
Sorted results on i5 laptop (smaller is better):
{
'mako': 0.0541565099847503,
'jinja': 0.26099945200257935,
'artless': 0.99770416400861,
'dtl': 1.07213215198135,
'fasthtml': 11.734292993991403
}
- Mako (0.05415 sec.)
- Jinja2 (0.26099 sec.)
- Artless-template (0.99770 sec.)
- Django templates (1.07213 sec.)
- FastHTML (11.73429 sec.)
The performance of artless-template
is better than the Django template engine
, and much better than FastHTML, but worse than Jinja2
and Mako
.
Roadmap
Related projects
- artless-core - the artless and minimalistic web library for creating small applications or APIs.