Globals are available in all templates without explicit passing.
Add Variables
from kida import Environment
env = Environment()
env.add_global("site_name", "My Site")
env.add_global("current_year", 2026)
env.add_global("debug_mode", False)
Template usage:
<title>{{ site_name }}</title>
<footer>© {{ current_year }}</footer>
Add Functions
from datetime import datetime
def now():
return datetime.now()
def format_date(dt, pattern="%Y-%m-%d"):
return dt.strftime(pattern)
env.add_global("now", now)
env.add_global("format_date", format_date)
Template usage:
<p>Generated: {{ format_date(now()) }}</p>
<p>Today: {{ format_date(now(), "%B %d, %Y") }}</p>
Add Classes
from collections import namedtuple
# Make types available
env.add_global("Counter", Counter)
env.add_global("namedtuple", namedtuple)
Built-in Globals
Kida includes common Python builtins:
range,len,str,int,float,booldict,list,set,tupleabs,min,max,sumsorted,reversed,enumerate,zipmap,filter
HTMX Helpers
Kida includes optional HTMX helpers for partial rendering and form security. Whenenable_htmx_helpers=True(default), these functions are available in all templates:
| Function | Returns | Description |
|---|---|---|
hx_request() |
bool |
True if the request is from HTMX |
hx_target() |
str | None |
HTMX target element ID from HX-Target header |
hx_trigger() |
str | None |
Element ID that triggered the request |
hx_boosted() |
bool |
True if request came from hx-boost="true" |
csrf_token() |
Markup |
Hidden input with CSRF token for forms |
Framework Integration
Frameworks must set metadata viarender_context().set_meta()before rendering:
from kida import Environment, render_context
with render_context() as ctx:
ctx.set_meta("hx_request", request.headers.get("HX-Request") == "true")
ctx.set_meta("hx_target", request.headers.get("HX-Target"))
ctx.set_meta("csrf_token", session.generate_csrf_token())
html = template.render(**data)
Template Usage
{% if hx_request() %}
{# Partial render — just the updated component #}
{% block content %}...{% end %}
{% else %}
{# Full page render #}
{% extends "base.html" %}
{% end %}
<form method="POST">
{{ csrf_token() }}
...
</form>
Disable HTMX helpers with Environment(enable_htmx_helpers=False).
Islands Helper Globals
For server-rendered apps that mount isolated high-state widgets, frameworks can register helper globals that generate safe island mount attributes.
import html
import json
from kida import Environment
env = Environment()
def island_attrs(name: str, props: dict, mount_id: str) -> str:
payload = html.escape(json.dumps(props, separators=(",", ":")), quote=True)
return (
f' data-island="{html.escape(name, quote=True)}"'
f' data-island-version="1"'
f' id="{html.escape(mount_id, quote=True)}"'
f' data-island-props="{payload}"'
)
env.add_global("island_attrs", island_attrs)
Template usage:
<div{{ island_attrs("editor", {"doc_id": doc.id}, "editor-root") }}>
<p>Fallback editor UI (SSR) if JS is unavailable.</p>
</div>
Auth Template Safety
For authentication views, keep template globals minimal and avoid exposing raw request/session objects.
from kida import render_context
with render_context() as ctx:
ctx.set_meta("csrf_token", csrf_token_value)
# Provide only explicit, safe values to templates.
html = template.render(current_user=user, next_url=safe_next_url)
Guidelines:
- Keep
autoescape=True(default). - Prefer explicit values (
current_user, IDs, flags) over full framework objects. - Use CSRF helpers from render metadata (
csrf_token) instead of hand-rolled fields. - Treat
Markupas trusted-only output.
Common Patterns
Site Configuration
site_config = {
"name": "My Site",
"url": "https://example.com",
"author": "Jane Doe",
}
env.add_global("site", site_config)
<a href="{{ site.url }}">{{ site.name }}</a>
<meta name="author" content="{{ site.author }}">
Utility Functions
import json
from urllib.parse import urlencode
env.add_global("json_encode", json.dumps)
env.add_global("urlencode", urlencode)
<script>const data = {{ json_encode(config) }};</script>
<a href="/search?{{ urlencode(params) }}">Search</a>
Feature Flags
features = {
"dark_mode": True,
"beta_features": False,
"analytics": True,
}
env.add_global("features", features)
{% if features.dark_mode %}
<link rel="stylesheet" href="/css/dark.css">
{% end %}
{% if features.analytics %}
{% include "analytics.html" %}
{% end %}
Request Context (Web)
def get_request_context(request):
return {
"user": request.user,
"path": request.path,
"is_authenticated": request.user.is_authenticated,
}
# Per-request globals
env.add_global("request", get_request_context(request))
Translation Function
import gettext
def _(text):
return translations.gettext(text)
env.add_global("_", _)
env.add_global("gettext", _)
<h1>{{ _("Welcome") }}</h1>
<p>{{ _("Hello, {}!").format(user.name) }}</p>
Dynamic Globals
For per-request values, update globals before rendering:
def render_with_context(template_name, **context):
# Add request-specific globals
env.add_global("current_user", get_current_user())
env.add_global("csrf_token", generate_csrf())
return env.render(template_name, **context)
Object as Namespace
Group related globals:
class Helpers:
@staticmethod
def format_date(dt, pattern="%Y-%m-%d"):
return dt.strftime(pattern)
@staticmethod
def truncate(text, length=100):
if len(text) <= length:
return text
return text[:length] + "..."
env.add_global("helpers", Helpers)
{{ helpers.format_date(post.date) }}
{{ helpers.truncate(post.content, 200) }}
Best Practices
Do Not Store UNDEFINED in Globals
env.globals should not contain the UNDEFINED sentinel. Values equal to UNDEFINED are filtered out when building the render context, so they will not appear in templates. Use UNDEFINED only as a lookup result (e.g. from _safe_getattr when an attribute is missing), not as a stored global. If you need a placeholder for "not yet defined," use None or a custom sentinel that is not UNDEFINED.
Immutable Configuration
# ✅ Configuration object
env.add_global("config", frozendict(settings))
# ❌ Mutable global
env.add_global("settings", mutable_dict)
Clear Naming
# ✅ Descriptive names
env.add_global("site_config", config)
env.add_global("format_currency", format_money)
# ❌ Vague names
env.add_global("c", config)
env.add_global("f", format_money)
Avoid Side Effects
# ✅ Pure function
env.add_global("add", lambda a, b: a + b)
# ❌ Function with side effects
def log_and_add(a, b):
print(f"Adding {a} + {b}") # Side effect
return a + b
See Also
- Rendering Contexts — Pass variables to templates
- Custom Filters — Transform values
- API Reference — Environment.add_global()