📑 Templates¶
Templates in Duck are used to generate dynamic HTML responses by combining static markup with runtime data (context).
They are typically rendered inside views and returned as HTTP responses.
Duck provides first-class support for two popular templating engines:
Django Templates — familiar, batteries-included, and tightly structured
Jinja2 — flexible, expressive, and widely used across Python ecosystems
You can freely choose which engine to use per render call.
🛠️ Rendering Functions¶
Duck exposes template rendering helpers through the ‘duck.shortcuts’ module.
These helpers abstract engine selection, context injection, and response creation.
Available Functions¶
‘render’
The default rendering function.Supports both Django and Jinja2
Engine selection is controlled via the ‘engine’ argument
‘django_render’
Explicitly renders templates using the Django template engine.‘jinja2_render’
Explicitly renders templates using the Jinja2 engine.‘async_render’
Asynchronous equivalent of ‘render’.Designed for async views
Behavior and arguments match ‘render’
⚙️ Template Syntax¶
Duck does not introduce a custom template language.
Instead, it fully embraces the native syntax of each supported engine.
1️⃣ Django Template Syntax¶
Django templates use a tag-based syntax with filters and template inheritance.
<h1>Hello {{ user.username }}</h1>
{% if user.is_authenticated %}
<p>Welcome back!</p>
{% else %}
<p>Please log in.</p>
{% endif %}
📖 Learn more:
Django Template Language Documentation
2️⃣ Jinja2 Template Syntax¶
Jinja2 templates are expressive and Pythonic, with powerful control structures.
<h1>Hello {{ user.username }}</h1>
{% if user.is_authenticated %}
<p>Welcome back!</p>
{% else %}
<p>Please log in.</p>
{% endif %}
📖 Learn more:
Jinja2 Template Documentation
📌 Template Locations¶
By default, Duck looks for templates in the global directory:
web/ui/templates
This directory is shared across the entire application.
Customizing Global Template Paths¶
You can override or extend global template directories by configuring:
GLOBAL_TEMPLATE_DIRS
inside your settings.py file.
🧪 Rendering Templates in Views¶
Synchronous View Example¶
from duck.shortcuts import render
def sync_view(request):
context = {
'title': 'Home',
}
return render(request, 'template.html', context, status_code=200)
Asynchronous View Example¶
from duck.shortcuts import async_render
async def async_view(request):
context = {
'title': 'Home',
}
return await async_render(request, 'template.html', context, status_code=200)
📗 Blueprint Templates¶
Duck supports template isolation per blueprint, making large applications easier to organize.
How Blueprint Templates Work¶
Each blueprint can expose its own template directory
By default, all blueprints are enabled for template rendering
Templates must live inside a ‘templates/’ directory within the blueprint path
Template Resolution¶
To render a blueprint template:
Prefix the template path with the blueprint name
Example structure:
docs/
├── templates/
│ └── index.html
Rendered as:
docs/index.html
Blueprint Rendering Example¶
from duck.shortcuts import render, async_render
def sync_view(request):
return render(
request,
'some_blueprint/template.html',
context={},
status_code=200,
)
async def async_view(request):
return await async_render(
request,
'some_blueprint/template.html',
context={},
status_code=200,
)
This approach keeps templates:
Modular
Reusable
Cleanly separated by application domain
✅ Summary¶
Duck supports Django and Jinja2 templates out of the box
Rendering helpers live in ‘duck.shortcuts’
Templates can be global or blueprint-scoped
Both sync and async rendering are supported
No custom syntax — use native engine features
👉 Next: Learn how to extend templates with 🏷️ Template Tags