No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Primer template para post

16/21
Recursos

Es momento de realizar el típico ¡Hola Mundo! Pero esta vez con un motor de renderizado de HTML como Tera.

Renderizado de HTML con Rust

Prepara tu proyecto para el renderizado de un HTML básico con Tera de la siguiente manera.

Paso 1. Instalación y preparación de TERA

Comienza instalando la dependencia de Tera en el Cargo.toml.

[dependencies]
tera = "1.10.0"

Impórtalo en el main.rs y configura el servidor HTTP para que reconozca la instancia de Tera y renderize los templates.

// Importamos TERA
use tera::Tera;

// ...

HttpServer::new(move || {

    // Instanciamos TERA y le indicamos en qué directorio buscar los templates
    let tera = Tera::new(concat!(env!("CARGO_MANIFEST_DIR"), "/templates/**/*")).unwrap();

    App::new()
        .service(index)
        .service(new_post)
        .service(tera_test)
        .app_data(web::Data::new(pool.clone()))
        .app_data(web::Data::new(tera.clone()))
}).bind(("127.0.0.1", 8080)).unwrap().run().await

Paso 2. Creación de templates

Crea un directorio al cual llamaremos /templates en la raíz de tu proyecto (a la altura de src) con un archivo llamado tera_test.html con un HTML básico en su interior.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Rust | Tera</title>
</head>
<body>
    Mi primer template HTML con Rust y Tera
</body>
</html>

Paso 3. Renderización HTML con endpoint

Finalmente, crea el endpoint que renderizará nuestro tera_test.html.

#[get("/tera_test")]
async fn tera_test(template_manager: web::Data<tera::Tera>) -> impl Responder {

    // Creamos un contexto para pasarle datos al template
    let mut ctx = tera::Context::new();

    // Enviamos el template que queremos localizándolo por su nombre
    HttpResponse::Ok().content_type("text/html").body(
        template_manager.render("tera_test.html", &ctx).unwrap()
    )
}

Si todo ha ido bien, simplemente ingresando a 127.0.0.1:8080/tera_test visualizarás el contenido del template.

De esta forma, ya puedes crear toda una página web estática con Rust y Tera. Pero aún queda lo mejor, enviar datos dinámicamente al template.


Contribución creada por: Kevin Fiorentino.

Aportes 4

Preguntas 0

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Asi se pasa el ‘state’ usando .app_data() en lugar de .data() que ha quedado obsoleto (deprecated).

//  --snip--
App::new()
	.service(index)
	.app_data(web::Data::new(pool.clone()))
	.app_data(web::Data::new(tera))

// --snip --

Documentació de Actix

Para que me funcionara tuve que poner unwrap al manifest dir y el nuevl app_data como comento Jose paredes

HttpServer::new(move || {

        let tera = Tera::new(concat!(env!("CARGO_MANIFEST_DIR"), "/templates/**/*")).unwrap();

        App::new()
        .service(index)
        .service(new_post)
        .app_data(web::Data::new(pool.clone()))
        .app_data(web::Data::new(tera))
    })
    .bind(("0.0.0.0", 9900))?
    .run()
    .await

Hubiese sido bueno aprender a configurar un logger para cuando hay problemas debuguear junto a la clase.

Cree otro template llamados posts.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Templates con Tera</title>
    <style>
        body {
            font-family: Arial, sans-serif;
        }

        table {
            width: 100%;
            border-collapse: collapse;
        }

        th,
        td {
            padding: 10px;
            border: 1px solid #000;
        }
    </style>
</head>

<body>
    <h1>Templates con Tera</h1>
    <table>
        <thead>
            <tr>
                <th>Title</th>
                <th>Body</th>
            </tr>
        </thead>
        <tbody>
            {% for post in posts %}
            <tr>
                <td>{{ post.title }}</td>
                <td>{{ post.body }}</td>
            </tr>
            {% endfor %}
        </tbody>
    </table>
</body>

</html>

Modifique #[get("/")] para que renderizara el resultado de la consulta de la tabla:

#[get("/")]
async fn index(pool: web::Data<DbPool>, template_manager: web::Data<tera::Tera>) -> impl Responder {
    let mut conn = pool.get().expect("Problemas al traer la BD");

    match web::block(move || posts.load::<Post>(&mut conn)).await {
        Ok(data) => {
            let mut context = tera::Context::new();
            context.insert("posts", &data.unwrap());
            let rendered = template_manager
                .render("posts.html", &context)
                .unwrap_or_else(|err| format!("Error al renderizar: {}", err));
            HttpResponse::Ok().content_type("text/html").body(rendered)
        }
        Err(err) => HttpResponse::Ok().body(format!("Error al recibir la data: {}", err)),
    }
}

El resultado: