Guide for rewriting Jinja2 templates in Kida syntax.
:::note[Not a Drop-In Replacement] Kida is not compatible with Jinja2. Templates must be rewritten using Kida syntax. This guide helps you translate common patterns. :::
Prerequisites
- Python 3.14+
- Familiarity with Jinja2 template syntax
Step 1: Install Kida
pip install kida
Step 2: Update Imports
Before (Jinja2):
from jinja2 import Environment, FileSystemLoader
from markupsafe import Markup
After (Kida):
from kida import Environment, FileSystemLoader
from kida import Markup # Built-in, no markupsafe
Step 3: Update Environment Creation
Before (Jinja2):
env = Environment(
loader=FileSystemLoader('templates'),
autoescape=select_autoescape(),
extensions=['jinja2.ext.do'],
)
After (Kida):
env = Environment(
loader=FileSystemLoader('templates'),
autoescape=True,
cache_size=400,
fragment_ttl=300.0,
)
Note: Kida does not use Jinja2-style extensions. For side effects, use{% set _ = expr %}.
Step 4: Rewrite Block Endings
Convert specific endings to unified{% end %}:
Jinja2:
{% if condition %}
content
{% endif %}
{% for item in items %}
{{ item }}
{% endfor %}
{% block content %}
...
{% endblock %}
Kida:
{% if condition %}
content
{% end %}
{% for item in items %}
{{ item }}
{% end %}
{% block content %}
...
{% end %}
Step 5: Update Custom Filters
Before (Jinja2):
def format_money(value, currency='$'):
return f'{currency}{value:,.2f}'
env.filters['money'] = format_money
After (Kida):
def format_money(value, currency='$'):
return f'{currency}{value:,.2f}'
env.add_filter('money', format_money)
# Or use the decorator
@env.filter()
def format_money(value, currency='$'):
return f'{currency}{value:,.2f}'
Step 6: Update Custom Tests
Before (Jinja2):
def is_prime(n):
return n > 1 and all(n % i for i in range(2, n))
env.tests['prime'] = is_prime
After (Kida):
env.add_test('prime', is_prime)
# Or use the decorator
@env.test()
def is_prime(n):
return n > 1 and all(n % i for i in range(2, n))
API Mapping
| Jinja2 | Kida |
|---|---|
Environment |
Environment |
FileSystemLoader |
FileSystemLoader |
DictLoader |
DictLoader |
Template.render() |
Template.render() |
Template.render_async() |
Template.render_async() |
Markup(markupsafe) |
Markup(built-in) |
env.filters[name] = func |
env.add_filter(name, func) |
env.tests[name] = func |
env.add_test(name, func) |
env.globals[name] = value |
env.add_global(name, value) |
Syntax Translation
| Jinja2 | Kida |
|---|---|
{% endif %} |
{% end %} |
{% endfor %} |
{% end %} |
{% endblock %} |
{% end %} |
{% endmacro %} |
{% end %} |
{{ x \| filter }} |
{{ x \|> filter }}(pipeline) |
{% if %}...{% elif %}...{% endif %} |
{% match %}...{% case %}...{% end %} |
| N/A | {% cache key %}...{% end %} |
New Features
After migrating, explore Kida-only features:
Pipeline Operator
{{ title |> escape |> upper |> truncate(50) }}
Pattern Matching
{% match status %}
{% case "active" %}
✓ Active
{% case "pending" %}
⏳ Pending
{% case _ %}
Unknown
{% end %}
Block Caching
{% cache "sidebar-" + user.id %}
{{ render_sidebar(user) }}
{% end %}
Verification
After migration, verify templates render correctly:
from kida import Environment
env = Environment()
template = env.from_string("Hello, {{ name }}!")
result = template.render(name="World")
assert result == "Hello, World!"
print("✅ Migration successful!")
Common Issues
Markup Import
Error:ImportError: cannot import name 'Markup' from 'markupsafe'
Fix: Import from Kida:
from kida import Markup # Not from markupsafe
Filter Registration
Error:TypeError: 'FilterRegistry' object does not support item assignment
Fix: Useadd_filter():
env.add_filter('name', func) # Not env.filters['name'] = func
Block Endings
Error:TemplateSyntaxError: Unexpected tag 'endif'
Fix: Use unified{% end %}:
{% if x %}...{% end %} # Not {% endif %}
See Also
- Control Flow — Pattern matching syntax
- Comparison — Kida vs Jinja2
- Performance — Benchmark results