Mako for Django
Mako powered template backend for Django.
Table of Contents
Overview
This backend integrates Mako directly into Django's template engine API. It supports Django's configuration, template discovery within app directories, and context processors, while extending them with Mako's syntax, performance, and detailed error handling.
Preview: Contextual line information
Preview: Runtime errors
Preview: Template postmortem
Motivation
Mako's multi-zoned inheritance feature can be used with the <%def> tag to
encapsulate structure and behavior, enabling modular and maintainable
templates. This approach provides a component-like system similar to
React
(JSX) or other modern
frameworks that support props and named/default slots. For technical details,
see the Defs and Blocks
section in the Mako documentation.
Demonstration
Component definition: button.html.mako
<%def
name="base_button(
class_name=None,
icon=None,
label=None,
round=False,
rounded=False,
)"
>
<button
class="${ clsx([
'button',
('button--round', round),
('button--rounded', rounded),
class_name,
]) }"
>
% if icon:
<span class="button__icon">
${ icon() }
</span>
% endif
% if label:
<span class="button__label">
${ label() }
</span>
% endif
</button>
</%def>
<%def name="basic_button(class_name=None, rounded=False)">
<%self:base_button
class_name="${ ['button--basic', class_name] }"
icon="${ getattr(caller, 'icon', None) }"
label="${ getattr(caller, 'label', None) }"
rounded="${ rounded }"
/>
</%def>
<%def name="icon_button(class_name=None, round=False)">
<%self:base_button
class_name="${ ['button--icon', class_name] }"
icon="${ getattr(caller, 'body', None) }"
round="${ round }"
/>
</%def>
[!TIP] The
clsxfunction is imported from clsx-py project, to manage class names dynamically.
Component usage: page.html.mako
<%namespace name="button" file="button.html.mako" />
<%button:icon_button class_name="sample-button">
➖
</%button:icon_button>
<%button:icon_button class_name="sample-button" round="${ True }">
➕
</%button:icon_button>
<%button:basic_button class_name="sample-button">
<%def name="icon()">✖️</%def>
<%def name="label()">Cancel</%def>
</%button:basic_button>
<%button:basic_button class_name="sample-button" rounded="${ True }">
<%def name="icon()">⚡</%def>
<%def name="label()">Trigger</%def>
</%button:basic_button>
Output
<button class="button button--icon sample-button">
<span class="button__icon">➖</span>
</button>
<button class="button button--round button--icon sample-button">
<span class="button__icon">➕</span>
</button>
<button class="button button--basic sample-button">
<span class="button__icon">✖️</span>
<span class="button__label">Cancel</span>
</button>
<button class="button button--rounded button--basic sample-button">
<span class="button__icon">⚡</span>
<span class="button__label">Trigger</span>
</button>
Installation
Available on PyPI:
pip install mako-for-django
Usage
Minimal configuration in settings.py:
TEMPLATES = [
{
"BACKEND": "django_mako.MakoEngine",
"DIRS": [
BASE_DIR / "mako",
],
"APP_DIRS": True,
"OPTIONS": {},
},
]
[!IMPORTANT] By default, templates within apps should be placed under a
makodirectory.
Example: Extending OPTIONS
MAKO_LOOKUP_OPTIONS = {
"cache_enabled": True,
# https://beaker.readthedocs.io/en/latest/
"cache_impl": "beaker",
}
MAKO_TEMPLATE_OPTIONS = {
"encoding_errors": "strict" if DEBUG else "htmlentityreplace",
}
TEMPLATES = [
{
"BACKEND": "django_mako.MakoEngine",
"DIRS": [
BASE_DIR / "mako",
],
"APP_DIRS": True,
"OPTIONS": {
"lookup": {
**MAKO_LOOKUP_OPTIONS,
},
"template": {
**MAKO_TEMPLATE_OPTIONS,
},
},
},
]
Example: Using Mako alongside DjangoTemplates
SHARED_TEMPLATE_CONTEXT_PROCESSORS = [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.template.context_processors.tz",
"django.template.context_processors.i18n",
"django.contrib.messages.context_processors.messages",
"django.template.context_processors.static",
"django.template.context_processors.media",
]
# Context processors to use with Mako backend only.
MAKO_TEMPLATE_CONTEXT_PROCESSORS = [
"django_mako.template.context_processors.url",
]
TEMPLATES = [
{
"BACKEND": "django_mako.MakoEngine",
"DIRS": [
BASE_DIR / "mako",
],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
*SHARED_TEMPLATE_CONTEXT_PROCESSORS,
*MAKO_TEMPLATE_CONTEXT_PROCESSORS,
],
},
},
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [
BASE_DIR / "templates",
],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
*SHARED_TEMPLATE_CONTEXT_PROCESSORS,
],
},
},
]
Tutorial
This tutorial guides you through creating a minimal Django project using Mako templates. Follow the steps to set up the project, add an application, create layout and page templates, and finally render a simple page in the browser.
By the end of this tutorial, the project structure should look like this:
demo/
├── demo/
│ ├── __init__.py
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── index/
│ ├── mako/
│ │ └── index/
│ │ └── views/
│ │ └── index.html.mako
│ ├── migrations/
│ │ └── __init__.py
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── mako/
│ └── layout.html.mako
└── manage.py
- Create a new Django project:
django-admin startproject demo
cd demo
- Create a new app inside the project:
python manage.py startapp index
- Enable the app in
settings.py:
INSTALLED_APPS = [
"index",
]
- Configure
MakoEngineinsettings.py:
TEMPLATES = [
{
"BACKEND": "django_mako.MakoEngine",
"DIRS": [
BASE_DIR / "mako",
],
"APP_DIRS": True,
"OPTIONS": {},
},
]
- Add layout template
mako/layout.html.mako:
<!DOCTYPE html>
<html>
<head>
<title><%block name="title">Demo</%block></title>
</head>
<body>
${ next.body() }
</body>
</html>
- Create page template
index/mako/index/views/index.html.mako:
<%inherit file="/layout.html.mako" />
<%block name="title">${ title } | ${ parent.title() }</%block>
<h1>${ title }</h1>
- Add view in
index/views.py:
from django.shortcuts import render
def index(request):
return render(
request,
# The template path, relative to `index/mako` directory.
"/index/views/index.html.mako",
{
"title": "Mako for Django",
},
)
- Wire up
urls.py:
from django.urls import path
from index.views import index
urlpatterns = [
path("", index),
]
- Run the server:
python manage.py runserver
After running the server, you can visit http://127.0.0.1:8000/.
Checkout the e2e directory for more examples.
git clone https://github.com/ertgl/mako-for-django.git
cd mako-for-django/e2e
make
python manage.py runserver
References
- Mako Templates for Python
- Templates | Django documentation
- How to implement a custom template backend | Django documentation
- django/template/backends - django/django on GitHub
Name
Published on PyPI as mako-for-django. The import name django_mako is chosen
for brevity.
License
This project is licensed under the MIT License. See the LICENSE file for details.
Metadata
Release files for mako-for-django 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| mako_for_django-1.0.0.tar.gz | 8.4 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mako_for_django-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 23.6 kB
Release files / mako_for_django-1.0.0.tar.gz
| Download URL | mako_for_django-1.0.0.tar.gz |
|---|---|
| Size | 8.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
943b97a35d52af8556893ab3d66e1508102524fb3892107dc2927d0af220bb30
|
|
BLAKE2b-256 checksum How to use checksums |
55faa21d7575dec3e0270a78123de9b1729f20fc83238525b9c861f6979a3d5b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.8.12
|
Release files / mako_for_django-1.0.0-py3-none-any.whl
| Download URL | mako_for_django-1.0.0-py3-none-any.whl |
|---|---|
| Size | 15.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
366080e46bb791cafc1caebe3ffc9ad67747b1272e6cc87c2fb06043b2360f24
|
|
BLAKE2b-256 checksum How to use checksums |
d4b1d695fc3276ed828a12f4db3970c8996a397cb24161c9907d49c549371cb9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.8.12
|
Security for mako-for-django 1.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.