djc / askama

Type-safe, compiled Jinja-like templates for Rust
Apache License 2.0
3.5k stars 221 forks source link

Document how askama_axum::Template is supposed to be used if the template rendering requires references to local variables #1106

Closed tibbe closed 1 week ago

tibbe commented 1 week ago

Assuming some code like this:

#[derive(Template)]
#[template(path = "hello.html")]
struct ListPostsTemplate<'a> {
    posts: &'a Vec<Post>,
}

async fn list_posts(
    State(pool): State<deadpool_diesel::sqlite::Pool>,
) -> Result<ListPostsTemplate<'static>, (StatusCode, String)> {
    let obj = pool.get().await.map_err(internal_error)?;
    let res = obj
        .interact(|conn| posts::table.select(Post::as_select()).load(conn))
        .await
        .map_err(internal_error)?
        .map_err(internal_error)?;
    let template = ListPostsTemplate { posts: res };
    Ok(template)
}

I get a borrowing error for res (and if I use &res I get an error for returning a reference to a local variable). Is this supposed to work? If we're not rendering the template before returning it it seems impossible to have rendering depend on any local variables, which I guess is the common case.

djc commented 1 week ago

You didn't show what error you're getting, but this is basic Rust/borrowing and nothing specific to Askama. You can't put a reference to a locally owned Vec and return it, because the Vec will be dropped before the caller gets the result. (You could render the Template before returning it, or store an owned Vec in ListPostsTemplate::posts.)