Templates

O Velox usa um sistema de templates similar ao Jinja2, com escape XSS automático.

Renderizar Templates

1. Usando app.render() (recomendado):

from velox import Velox

app = Velox(__name__)
app.template('templates')  # Define a pasta de templates

@app.get('/')
def home(req, res):
    # Renderiza template com contexto
    return app.render('index.html', {
        'title': 'Minha Página',
        'name': 'João',
        'users': [{'name': 'Alice'}, {'name': 'Bob'}]
    })

2. Usando res.html() com template:

@app.get('/pagina')
def pagina(req, res):
    html = app.render('pagina.html', {'msg': 'Olá!'})
    res.html(html)

3. Sem template (HTML direto):

@app.get('/')
def home(req, res):
    res.html('<h1>Olá Mundo!</h1>')

Variáveis no Template

No arquivo templates/index.html:

<!DOCTYPE html>
<html>
<head>
    <title>{{ title }}</title>
</head>
<body>
    <h1>Olá, {{ name }}!</h1>

    <!-- Acessar objetos -->
    <p>Primeiro usuário: {{ users.0.name }}</p>

    <!-- Acessar atributos -->
    <p>Email: {{ user.email }}</p>
</body>
</html>

Variáveis são escapadas automaticamente contra XSS. Use |safe para HTML confiável:

<!-- Escape automático (safe) -->
{{ conteudo_html }}  <!-- escapa <script> -->

<!-- HTML seguro (não escapa) -->
{{ conteudo_html|safe }}

Condicionais

{% if user %}
    <p>Bem-vindo, {{ user.name }}!</p>
{% else %}
    <p>Bem-vindo, visitante!</p>
{% endif %}

{% if count > 10 %}
    <span class="badge">Mais de 10 itens</span>
{% elif count > 5 %}
    <span class="badge">Entre 5 e 10</span>
{% else %}
    <span class="badge">Poucos itens</span>
{% endif %}

Loops (For)

<ul>
{% for user in users %}
    <li>{{ user.name }} - {{ user.email }}</li>
{% endfor %}
</ul>

<!-- Com índice -->
{% for user in users %}
    <p>{{ forloop.index }}: {{ user.name }}</p>
{% endfor %}

Variáveis disponíveis no loop: - forloop.index - posição atual (1-based) - forloop.index0 - posição atual (0-based) - forloop.first - True se primeiro - forloop.last - True se último - forloop.length - total de items

Herança de Templates

templates/base.html:

<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}Velox{% endblock %}</title>
    <link rel="stylesheet" href="/static/css/style.css">
</head>
<body>
    <header>
        <nav>
            <a href="/">Home</a>
            <a href="/sobre">Sobre</a>
        </nav>
    </header>

    <main>
        {% block content %}{% endblock %}
    </main>

    <footer>
        © 2026 Meu Site
    </footer>
</body>
</html>

templates/index.html:

{% extends "base.html" %}

{% block title %}Página Inicial{% endblock %}

{% block content %}
    <h1>Bem-vindo!</h1>
    <p>Esta é a página inicial.</p>
{% endblock %}

Includes

header.html:

<header>
    <h1>Meu Site</h1>
    <nav>
        <a href="/">Home</a>
        <a href="/sobre">Sobre</a>
    </nav>
</header>

footer.html:

<footer>
    <p>© 2026 - Todos os direitos reservados</p>
</footer>

index.html (com includes):

{% include "header.html" %}

<main>
    <h1>Página Principal</h1>
    {% include "components/alerta.html" with msg="Olá!" %}
</main>

{% include "footer.html" %}

Filtros

<!-- Textos -->
{{ name|upper }}           <!-- JOÃO -->
{{ name|lower }}           <!-- joão -->
{{ name|title }}           <!-- João -->

<!-- Strings -->
{{ text|truncate:50 }}     <!-- Primeiros 50 chars... -->
{{ text|striptags }}       <!-- Remove tags HTML -->
{{ text|default:"N/A" }}   <!-- Valor padrão -->

<!-- Listas -->
{{ items|length }}         <!-- Total de items -->
{{ items|first }}          <!-- Primeiro item -->
{{ items|last }}           <!-- Último item -->
{{ items|join:", " }}      <!-- item1, item2 -->

<!-- Números -->
{{ price|currency:"R$" }}  <!-- R$ 10,50 -->
{{ num|format:"%.2f" }}     <!-- 10.50 -->

<!-- Datas -->
{{ date|date:"%d/%m/%Y" }}  <!-- 25/03/2026 -->

<!-- HTML -->
{{ html|safe }}            <!-- Não escapa -->

Static Files (CSS/JS)

Configure no app.py:

from velox import Velox

app = Velox(__name__)
app.template('templates')
app.static('static')  # Pasta de arquivos estáticos

No template:

<link rel="stylesheet" href="/static/css/style.css">
<script src="/static/js/app.js"></script>
<img src="/static/img/logo.png">

Estrutura:

projeto/
├── app.py
├── static/
│   ├── css/
│   │   └── style.css
│   ├── js/
│   │   └── app.js
│   └── img/
│       └── logo.png
└── templates/
    └── index.html

Exemplo Completo

app.py:

from velox import Velox

app = Velox(__name__)
app.template('templates')
app.static('static')

@app.get('/')
def home(req, res):
    users = [
        {'name': 'Alice', 'email': 'alice@email.com'},
        {'name': 'Bob', 'email': 'bob@email.com'},
    ]
    return app.render('index.html', {
        'title': 'Home',
        'users': users,
        'count': len(users),
    })

@app.get('/sobre')
def sobre(req, res):
    res.html('<h1>Sobre Nós</h1><p>Página sobre.</p>')

if __name__ == '__main__':
    app.run()

templates/index.html:

{% extends "base.html" %}

{% block title %}{{ title }}{% endblock %}

{% block content %}
    <h1>Bem-vindo!</h1>

    <p>Total de usuários: {{ count }}</p>

    <ul>
    {% for user in users %}
        <li>
            <strong>{{ user.name|title }}</strong> -
            <a href="mailto:{{ user.email }}">{{ user.email }}</a>
        </li>
    {% empty %}
        <li>Nenhum usuário cadastrado.</li>
    {% endfor %}
    </ul>

    {% if count > 0 %}
        <p>Há usuários registrados!</p>
    {% endif %}
{% endblock %}