Creación de Templates Dinámicos con Tera en Rust

Clase 17 de 21Curso de Backend con Rust: Bases de Datos, Controladores y Templates

Contenido del curso

Gestión de modelos en el backend con el ORM Diesel

Resumen

Puedes crear tantas páginas HTML como tu aplicación necesite. En cualquier página web es fundamental poder enviar información dinámicamente al template.

Pasaje de variables al template

Vamos a crear una página HTML para mostrar todos los registros. Para esto, modifica el index de tu aplicación para que devuelva un "contexto" y lograr pasarle datos a tu HTML.

#[get("/")] async fn index(pool: web::Data<DbPool>, template_manager: web::Data<tera::Tera>) -> impl Responder { let conn = pool.get().expect("Problemas al traer la base de datos"); // Consulta para obtener todos los registros match web::block(move || {posts.load::<Post>(&conn)}).await { Ok(data) => { let data = data.unwrap(); // Enviamos, a través del contexto, los datos al HTML let mut ctx = tera::Context::new(); ctx.insert("posts", &data); // Pasamos los datos al template index.html HttpResponse::Ok().content_type("text/html").body( template_manager.render("index.html", &ctx).unwrap() ) }, Err(err) => HttpResponse::Ok().body("Error al recibir la data") } }

En cuanto al HTML, Tera utiliza un lenguaje especial y muy fácil de utilizar para mostrar los datos o crear un ciclo for.

<!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>Document</title> </head> <body> {% for post in posts %} <div> <h1> <a href="/blog/{{post.slug}}">{{ post.title }} </a> </h1> <p>{{ post.body }}</p> </div> {% endfor %} </body> </html>

A la vez que mostramos el título y la descripción del registro, estamos generando un enlace HTML para redireccionar a la página exclusiva del registro.

Captura de parámetros

Para crear una página exclusiva para cada registro, normalmente se pasa un ID o una clave única del mismo a través de los parámetros de URL. Vamos a crear una nueva página para capturar esta información y renderizar un solo registro.

// Capturamos el parámetro por URL #[get("/blog/{blog_slug}")] async fn get_post( pool: web::Data<DbPool>, template_manager: web::Data<tera::Tera>, blog_slug: web::Path<String> ) -> impl Responder { let conn = pool.get().expect("Problemas al traer la base de datos"); let url_slug = blog_slug.into_inner(); match web::block(move || {posts.filter(slug.eq(url_slug)).load::<Post>(&conn)}).await { Ok(data) => { let data = data.unwrap(); // Si el post no existe, devolvemos 404 if data.len() == 0 { return HttpResponse::NotFound().finish(); } let data = &data[0]; // Enviamos, a través del contexto, los datos del post al HTML let mut ctx = tera::Context::new(); ctx.insert("post", data); HttpResponse::Ok().content_type("text/html").body( template_manager.render("post.html", &ctx).unwrap() ) }, Err(err) => HttpResponse::Ok().body("Error al recibir la data") } }

El URL está compuesto por una variable dinámica /blog/{blog_slug} la cual podemos capturar como parámetro gracias a blog_slug: web::Path<String>. Con este dato, buscamos y devolvemos el registro correspondiente o devolvemos 404 si el mismo no existe.

Mientras que en el HTML, solo muestras la información de un solo registro.

<!DOCTYPE html> <html lang="es"> <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>{{ post.title }}</title> </head> <body> <div> <h1>{{ post.title }}</h1> <p>{{ post.body }}</p> <a href="/">Volver</a> </div> </body> </html>

De esta forma, ya sabes exponer un servidor HTTP con Rust y Actix, conectarte a una base de datos SQL con Diesel y renderizar la información en un template HTML con Tera. Hemos completado todo el stack necesario para desarrollar tu primera página web con Rust. ¡Felicidades!


Contribución creada por: Kevin Fiorentino.

      Creación de Templates Dinámicos con Tera en Rust