I am trying to render a template with Rust Rocket and Handlebars. This compiles but I can't get any arguments to the HTML file to work. The page loads, but the argument is not there. I am familiar with flask and jinja for Python but not as much with Rocket and Handlebars. I have tried countless things but I can't find any documentation that works.
#![feature(decl_macro)]
extern crate rocket;
extern crate rocket_contrib;
use rocket::{get, routes};
use rocket_contrib::templates::Template;
#[get("/one")]
fn one() -> String {
format!("One")
}
#[get("/page")]
fn page() -> Template {
let context = "string";
Template::render("page", &context)
}
fn main() {
rocket::ignite()
.mount("/", routes![one])
.attach(Template::fairing())
.launch();
}
page.html.hbs
<!DOCTYPE html>
<head></head>
<html>
<body>
<h1>Argument is: {{context}}</h1>
</body>
</html>
The template system doesn't know that the local variable is called context
. It just knows that your context is a string, which doesn't have an attribute called context
. You need to provide a type implementing Serialize
, with a member called context
for the template expression {{context}}
to expand to anything. You could do this with a HashMap
or a custom type.
With a HashMap
:
#[get("/page")]
fn page() -> Template {
let mut context = HashMap::new();
context.insert("context", "string");
Template::render("page", &context)
}
With a custom type:
#[get("/page")]
fn page() -> Template {
#[derive(serde_derive::Serialize)]
struct PageContext {
pub context: String,
}
let context = PageContext { context: "string" };
Template::render("page", &context)
}
Custom types will generally perform better, and are self-documenting.