Use Kida through Django's standard template-backend contract, then render a named fragment from the same template. Kida requires Python 3.14 or newer.
Migrating Jinja templates? Read Coming from Jinja2. Kida's
{% set %}is block-scoped, so values do not leak out of loops or other blocks.
1. Install
uv add django kida-templates
2. Configure the backend
Add Kida toTEMPLATES in settings.py:
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
TEMPLATES = [
{
"NAME": "kida",
"BACKEND": "kida.contrib.django.KidaTemplates",
"DIRS": [BASE_DIR / "templates"],
"APP_DIRS": False,
"OPTIONS": {"autoescape": True},
},
]
NAMEmakes the backend easy to select explicitly when an application uses
more than one template engine.
3. Add full-page and fragment views
from django.http import HttpRequest, HttpResponse
from django.middleware.csrf import get_token
from django.shortcuts import render
from django.template import engines
def home(request: HttpRequest) -> HttpResponse:
return render(
request,
"components.html",
{
"title": "First component",
"summary": "Edit me",
"csrf_token": get_token(request),
},
using="kida",
)
def preview(request: HttpRequest) -> HttpResponse:
template = engines["kida"].env.get_template("components.html")
html = template.render_block(
"preview",
title=request.POST.get("title", ""),
summary=request.POST.get("summary", ""),
)
return HttpResponse(html)
Wire the views normally:
from django.urls import path
from . import views
urlpatterns = [
path("", views.home),
path("preview", views.preview),
]
The backend wrapper supports Django's normal render()path and supplies the
request in template context. Accessingbackend.envis the supported route to
Kida-specific APIs such asrender_block().
4. Create the typed component
Save this astemplates/components.html:
{% def panel(title: str) %}
<section class="panel">
<h1>{{ title }}</h1>
{% slot %}
</section>
{% enddef %}
{% def text_field(name: str, label: str, value: str = "") %}
<label>
{{ label }}
<input name="{{ name }}" value="{{ value }}">
</label>
{% enddef %}
{% block form %}
{% call panel("Component form") %}
<form method="post" action="/preview">
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">
{{ text_field("title", "Title", title) }}
{{ text_field("summary", "Summary", summary) }}
<button type="submit">Preview</button>
</form>
{% endcall %}
{% endblock %}
{% block preview %}
<article id="preview">
<h2>{{ title }}</h2>
<p>{{ summary }}</p>
</article>
{% endblock %}
Kida validates component calls against their typed signatures. The full view
and fragment view share compilation and escaping behavior; the fragment route
returns onlypreviewfor HTMX, Turbo, or a similar client.
5. Run it
uv run python manage.py runserver
The repository includes a minimal, smoke-tested Django configuration at
examples/django_components.
Register filters and globals
Use the named backend from application startup code:
from django.template import engines
env = engines["kida"].env
@env.filter()
def currency(value: float) -> str:
return f"${value:,.2f}"
env.add_global("SITE_NAME", "My Django Site")