Skip to content

Templates

Ushka uses the powerful Jinja2 templating engine to generate dynamic HTML content.

Rendering Templates

To render a template from a view, use the ushka.contrib.templating.render function.

# in apps/home/views.py
from ushka.contrib.templating import render
from ushka.http import Request

async def get_index(request: Request):
    context = {
        "page_title": "Welcome!",
        "items": ["Apple", "Banana", "Cherry"]
    }
    return render("index.html", context)

The render() function takes two arguments: 1. The name of the template file. 2. A dictionary of context variables to make available within the template.

The TemplateIntent

The render() function doesn't return a rendered HTML string directly. Instead, it returns a TemplateIntent object. The Ushka framework intercepts this object later in the request lifecycle to perform the actual rendering. This allows the framework to automatically inject global context variables (like request or settings) into every template.

Template Discovery

Ushka automatically looks for templates in several locations, in a specific order of priority. This allows you to override framework or app templates with your own project-level templates.

The search order is: 1. Project templates/ directory: my_project/templates/ 2. App templates/ directories: my_project/apps/<app_name>/templates/ 3. Ushka's internal templates: Default error pages, admin panel templates, etc.

So, if you have a file my_project/templates/admin/login.html, it will be used instead of Ushka's built-in admin login template.

Template Context

Inside a template, you have access to all the variables you passed in the context dictionary.

<!-- in templates/index.html -->
<!DOCTYPE html>
<html>
<head>
    <title>{{ page_title }}</title>
</head>
<body>
    <h1>Items</h1>
    <ul>
    {% for item in items %}
        <li>{{ item }}</li>
    {% endfor %}
    </ul>
</body>
</html>

Global Context

Ushka automatically injects the following variables into every template's context:

  • request: The current Request object.
  • settings: The application's Settings object.
  • app_name: The name of your application, from ushka.toml.

This means you can do things like this in any template without passing them in manually:

<p>You are visiting from {{ request.headers.get('user-agent') }}.</p>
<p>Running {{ app_name }} in debug mode: {{ settings.app.debug }}</p>

Flashing Messages

Flash messages are a way to store a message in a user's session and display it on the next request they make. This is very common for showing success or error messages after a form submission and redirect.

Ushka's flash system is available as a context processor, so it's ready to use in templates out of the box.

1. Flash a message in your view:

from ushka.contrib.templating.flash import flash, Category
from ushka.http import redirect

async def post_update_profile(request: Request):
    # ... update logic ...
    flash(request, "Your profile has been updated!", Category.SUCCESS)
    return redirect("/profile")

2. Display the message in your template:

The messages variable will be available in your template. It's a list of (category, message) tuples.

<!-- in your base layout or profile template -->
{% if messages %}
    <div class="flashes">
    {% for category, message in messages %}
        <div class="flash-{{ category }}">{{ message }}</div>
    {% endfor %}
    </div>
{% endif %}

The available categories are SUCCESS, DANGER, WARNING, and INFO.