Template Rendering in Rust using Askama

on 2023-06-02

Introduction


In this tutorial, we will explore the usage of Askama library for template rendering in Rust. Let's create a simple music store application(as shown below) which allows us to add, update and delete information.


list_music web page

Setup


Create a new cargo project music_store using the following command.

cargo new music_store
cd music_store

Add the following dependencies to Cargo.toml file.

tokio = { version = "1.28.1", features = ["full"] }
actix-web = "4.3.1"
askama = "0.12.0"
askama_actix = "0.14.0"
serde = { version = "1.0.163", features = ["derive"] }
lazy_static = "1.4.0"

tokio and actix-web libraries are used for building asynchronous and concurrent web applications. askama library is used for templating and askama_actix is an integration library that bridges askama and actix-web. serde is used to serialize/deserialize request payload. lazy_static is used to initialize static global variables at runtime.

Create Templates


Adding HTML files

Create a directory named templates in crate root. Our directory structure will look like this.

music_store
├── Cargo.toml
├── src
│   ├── main.rs
└── templates

Now let's create a welcome page by adding index.html to templates directory. We will be using Bootstrap to create HTML pages.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
    <title>Music Store</title>
</head>
<body>
<div class="container">

    <h1>Music Store</h1>

    {% block add_music %}{% endblock %}
    {% block music_list %}{% endblock %}

</div>
</body>
</html>

We will see the usage of add_music and music_list blocks in the later part of the tutorial.

Template Rendering

To render templates, we have to implement Template trait, from the askama library, for any struct type in Rust. We can easily do that using derive macro.

Create http_handles.rs file in src directory.

use askama_actix::Template;

#[derive(Template)]
#[template(path = "index.html")]
pub struct WelcomePage;

pub async fn welcome() -> WelcomePage { WelcomePage }

We have defined an empty struct WelcomePage which implements Template trait and set the path to the template file using template() attribute.

Starting Web Server


We will configure routes in the HTTP server to call welcome function from http_handlers.rs

Add the below code to main.rs

mod http_handlers;

use actix_web::web::ServiceConfig;
use actix_web::{App, HttpServer, web};
use crate::http_handlers::*;

#[tokio::main]
async fn main() {
    if let Err(e) = start_server().await {
        println!("Error while starting http server {}", e);
    }
}

async fn start_server() -> std::io::Result<()> {
    println!("Starting server at http://127.0.0.1:8000/");
    HttpServer::new(|| App::new().configure(routes))
        .bind(("127.0.0.1", 8000))?
        .run()
        .await
}

fn routes(service_config: &mut ServiceConfig) {
    service_config.route("/", web::get().to(welcome));
}

Build and run the project to start the server.

cargo run

You should be seeing below webpage on http://127.0.0.1:8000

music store web page


Check out Part-2 of the tutorial where we will add data to DB and view them. 😀