I want to display a value retrieved from the database with Diesel and serve it as HTML using a Tera template with Rocket:
#[get("/")]
fn index(db: DB) -> Template {
use mlib::schema::users::dsl::*;
let query = users.first::<User>(db.conn()).expect("Error loading users");
let serialized = serde_json::to_string(&query).unwrap();
println!("query = {:?}", &serialized);
Template::render("index", &serialized)
}
It receives User { id: 1, name: "yamada" }
from the database in #[get("/")]
of src/main.rs
and tries to render it with a template. It looks good to me, but this error is returned:
Error: Error rendering Tera template 'index': Failed to value_render 'index.html.tera': context isn't an object
The error message is telling you everything you need to know:
context isn't an object
And what is context
? Check out the docs for Template::render
:
fn render<S, T>(name: S, context: &T) -> Template
where S: AsRef<str>,
T: Serialize,
This MCVE shows the problem:
src/main.rs
#![feature(plugin)]
#![plugin(rocket_codegen)]
extern crate rocket;
extern crate rocket_contrib;
use rocket_contrib::Template;
#[get("/")]
fn index() -> Template {
let serialized = "hello".to_string();
Template::render("index", &serialized)
}
fn main() {
rocket::ignite().mount("/", routes![index]).launch();
}
Cargo.toml
[dependencies]
rocket = "0.1.6"
rocket_codegen = "0.1.6"
[dependencies.rocket_contrib]
version = "0.1.6"
features = ['tera_templates']
templates/index.html.tera
<html />
Most templating engines work against a data structure that maps a name to a value. In many cases, this is something as simple as a HashMap
, but Rocket allows you to pass in anything that can be serialized. This is intended to allow passing in a struct, but it also allows you to pass in things that do not map names to values, like a pure string.
You have two choices:
HashMap
(or maybe a BTreeMap
) of values.Serialize
for a struct and pass that in.Here's the first option:
use std::collections::HashMap;
let mut serialized = HashMap::new();
serialized.insert("greeting", "hello");
Template::render("index", &serialized)