Skip to content

TemplateConfig

Configure template rendering for server-side HTML generation in your Ravyn application.

What You'll Learn

  • Setting up Jinja2 templates
  • Rendering templates
  • Using async templates
  • Template best practices

Quick Start

from ravyn import Ravyn, get
from ravyn.config import TemplateConfig
from ravyn.responses import Template

app = Ravyn(
    template_config=TemplateConfig(
        directory="templates"
    )
)

@get("/")
def homepage() -> Template:
    return Template("index.html", context={"title": "Home"})

Basic Configuration

Minimal Setup

from ravyn import Ravyn
from ravyn.config import TemplateConfig

app = Ravyn(
    template_config=TemplateConfig(
        directory="templates"
    )
)

Complete Configuration

app = Ravyn(
    template_config=TemplateConfig(
        directory="templates",
        autoescape=True,
        auto_reload=True,  # Development only
        enable_async=True  # For async templates
    )
)

Configuration Parameters

Parameter Type Description Default
directory str/list Template directory path(s) Required
autoescape bool Auto-escape HTML True
auto_reload bool Reload templates on change False
enable_async bool Enable async templates False

Rendering Templates

Basic Template

from ravyn import get
from ravyn.responses import Template

@get("/")
def homepage() -> Template:
    return Template("index.html")

templates/index.html:

<!DOCTYPE html>
<html>
<head>
    <title>Home</title>
</head>
<body>
    <h1>Welcome to Ravyn!</h1>
</body>
</html>

With Context Data

@get("/users/{user_id}")
async def user_profile(user_id: int) -> Template:
    user = await User.get(id=user_id)

    return Template(
        "profile.html",
        context={
            "user": user,
            "title": f"Profile - {user.name}"
        }
    )

templates/profile.html:

<!DOCTYPE html>
<html>
<head>
    <title>{{ title }}</title>
</head>
<body>
    <h1>{{ user.name }}</h1>
    <p>Email: {{ user.email }}</p>
</body>
</html>


Async Templates

Enable async templates for async database queries:

Configuration

app = Ravyn(
    template_config=TemplateConfig(
        directory="templates",
        enable_async=True  # Enable async
    )
)

Using Async in Templates

@get("/products")
async def products() -> Template:
    # Pass QuerySet directly
    products = Product.query.all()  # Async QuerySet

    return Template(
        "products.html",
        context={"products": products}
    )

templates/products.html:

<ul>
{% for product in products %}
    <li>{{ product.name }} - ${{ product.price }}</li>
{% endfor %}
</ul>

[!INFO] With enable_async=True, Jinja2 automatically resolves async iterables.


Built-in Template Functions

url_for

Generate URLs for routes:

<a href="{{ url_for('homepage') }}">Home</a>
<a href="{{ url_for('user_profile', user_id=123) }}">Profile</a>

Template Inheritance

base.html:

<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}My Site{% endblock %}</title>
</head>
<body>
    {% block content %}{% endblock %}
</body>
</html>

page.html:

{% extends "base.html" %}

{% block title %}Page Title{% endblock %}

{% block content %}
    <h1>Page Content</h1>
{% endblock %}


Using with Settings

from ravyn import RavynSettings
from ravyn.config import TemplateConfig

class AppSettings(RavynSettings):
    template_config: TemplateConfig = TemplateConfig(
        directory="templates",
        autoescape=True,
        enable_async=True
    )

app = Ravyn(settings_module=AppSettings)

Common Patterns

Pattern 1: Layout with Partials

<!-- base.html -->
<!DOCTYPE html>
<html>
<head>
    {% include "partials/head.html" %}
</head>
<body>
    {% include "partials/header.html" %}
    {% block content %}{% endblock %}
    {% include "partials/footer.html" %}
</body>
</html>

Pattern 2: Form Rendering

@get("/contact")
def contact_form() -> Template:
    return Template("contact.html")

@post("/contact")
async def submit_contact(name: str, email: str, message: str) -> Template:
    await send_email(name, email, message)

    return Template(
        "contact.html",
        context={"success": True}
    )

Pattern 3: Error Pages

from ravyn import Ravyn
from ravyn.responses import Template

app = Ravyn(
    template_config=TemplateConfig(directory="templates")
)

@app.exception_handler(404)
async def not_found(request, exc) -> Template:
    return Template("404.html", status_code=404)

@app.exception_handler(500)
async def server_error(request, exc) -> Template:
    return Template("500.html", status_code=500)

Best Practices

1. Organize Templates

templates/
  base.html
  index.html
  partials/
    header.html
    footer.html
  users/
    profile.html
    list.html
  errors/
    404.html
    500.html

2. Use Template Inheritance

<!-- Good - reuse base layout -->
{% extends "base.html" %}

{% block content %}
    <h1>Page Content</h1>
{% endblock %}

3. Enable Auto-Escape

# Good - prevent XSS
template_config = TemplateConfig(
    directory="templates",
    autoescape=True  # Always escape HTML
)

Next Steps