Template Engines

Libraries for rendering text and HTML from templates.

Whether templates may hold Python code splits the Python template engines: Jinja keeps code out and sandboxes untrusted templates, Mako embeds plain Python.

How to choose:

  • Templates without embedded Python: Jinja
  • Templates your users write: Jinja, in its sandbox
  • Plain Python inside your templates: Mako

Listed in editorial order. Click a column header to re-sort the whole list.

Press / to search. Tags open their category. Click a row for details.

Search and filter

Results

Row number Tags
A modern and designer-friendly templating language.
pallets/github.com/pallets/jinja /11,808 stars /
Hyperfast and lightweight templating for the Python platform.
sqlalchemy/github.com/sqlalchemy/mako /461 stars /

Template Engines guide

Jinja doesn't allow arbitrary Python code in templates: you get blocks, filters, and function calls, and the rest of your logic stays in Python. Outside a framework, create one Environment when your app starts and load templates through a PackageLoader. Put the layout your pages share in a base template, and let each page extend it and override its blocks. Flask sets up Jinja for you, Django has a built-in Jinja2 backend, and FastAPI supports it with Jinja2Templates.

When your users write templates, like a report layout, render them in Jinja's sandbox, which can block attribute access, method calls, and other operations. Its docs say the sandbox alone is not a solution for perfect security: catch errors when a template renders, limit CPU and memory, and pass the template only the data it needs.

Mako is an embedded Python language: inside <% %> tags you write regular Python. A real application loads its templates from a TemplateLookup with a module_directory, which caches each compiled template on disk as a Python module.

Jinja leaves HTML escaping off by default, since it also renders plain text, emails, and config files. When you create the Environment yourself, turn it on with select_autoescape(); Flask turns it on for HTML templates, and Django's Jinja2 backend turns it on for all. Mako escapes HTML only through the h filter: add it to default_filters on your TemplateLookup to escape every expression.

Know a project that belongs here?

Tell us what it does and why it stands out.