Skip to main content

Templates

OxAPY ships a template engine based on Tera (a Jinja2-like language) for rendering server-side HTML. See the Tera documentation for the full template syntax reference.

Enabling templates​

Create a Template instance, configure it, and attach it to the server:

from oxapy import Oxapy, Router, get, render, templating


def main():
template = templating.Template() # loads ./templates/**/*.html by default

(
Oxapy(("127.0.0.1", 5555))
.template(template)
.attach(Router().route(index))
.run()
)

The template directory defaults to ./templates/**/*.html. Pass a glob pattern to use another directory:

template = templating.Template("./views/**/*.html")

Rendering from a handler​

The render(request, name, context) function renders a template and returns an HTML response:

from oxapy import Router, get, render


@get("/")
def index(request):
return render(request, "index.html", {"title": "Home Page"})

Given this template file templates/index.html:

<!DOCTYPE html>
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<h1>{{ title }}</h1>
<ul>
{% for item in items %}
<li>{{ item }}</li>
{% endfor %}
</ul>
</body>
</html>

The rendered page is served with Content-Type: text/html. When the session is set on the request, it is made available to templates as {{ session }} automatically.

Automatic template variables​

The render() function injects variables into the template context based on active middleware:

VariableSourceDescription
sessionSession middlewareThe session dictionary from request.session
csrf_tokenCsrfProtect middlewareThe CSRF token string from request.csrf_token

When CsrfProtect is active, the built-in csrf_input template function is also available:

<form method="POST" action="/submit">
{{ csrf_input(token=csrf_token) }}
<input type="text" name="username" />
<button type="submit">Submit</button>
</form>

This renders a hidden <input> with the token — no manual passing required. See the CSRF Protection guide for details.

Custom template functions​

Register Python functions that templates can call, such as a translation helper:

def translate(key):
translations = {"hello": "Bonjour"}
return translations.get(key, key)


def main():
template = templating.Template()
template.register_function("_t", translate)
template.load()
...
<p>{{ _t(key="hello") }}</p>
warning

Register all custom functions before calling load(). Tera validates function references when templates are loaded, and register_function() raises a RuntimeError after load() has been called.

Template lifecycle​

  • Template() creates an empty engine; nothing is loaded yet.
  • register_function(name, callable) exposes a Python callable to templates (must be called before load()).
  • load(dir="./templates/**/*.html") parses and validates all matching templates.
  • render(request, name, context) renders a template and returns a Response.

Next steps​