4

我正在用 rust Rocket 写一个小网站。我正在使用车把模板,您返回Template表单处理程序的方式非常方便。但我也想将我的模板引擎用于我发送的电子邮件。问题是,其中的模板rocket_contrib并不真正支持渲染到String.

有一种方法show()可以创建Option<String>,但不应该使用该方法。

将位于路径根目录下的名为 name 的模板与上下文上下文一起呈现为字符串。这种方法非常慢,不应该在任何正在运行的 Rocket 应用程序中使用。此方法仅应在测试期间用于验证模板响应。对于其他用途,请render改用。

该方法render()是您通常使用的方法,但是这个方法返回 a Template,这就是我开始使用的方法...您返回这些方法,并且 Rocket 会发挥它的魔力来生成生成的 html 页面。

有什么方法可以在 Rocket 中使用我的模板来发送电子邮件?我的邮件 (lettre) 需要一个字符串。

4

1 回答 1

2

使用起来完全没问题show()。以下是它的实现方式Rocket

    pub fn show<S, C>(rocket: &Rocket, name: S, context: C) -> Option<String>
        where S: Into<Cow<'static, str>>, C: Serialize
    {
        let ctxt = rocket.state::<ContextManager>().map(ContextManager::context).or_else(|| {
            // N.B.: removed some logging for brevity
            None
        })?;

        Template::render(name, context).finalize(&ctxt).ok().map(|v| v.0)
    }

正如你所看到的show() ,确实在内部调用render(),就像 rustdoc 告诉我们的那样。但这里它也调用finalize(). 让我们检查一下它的作用:

/// Actually render this template given a template context. This method is
/// called by the `Template` `Responder` implementation as well as
/// `Template::show()`.

好的,所以render()并没有真正渲染任何东西。它finalize()正在做这项工作。

我们还可以检查它是如何Responder实现的:

/// Returns a response with the Content-Type derived from the template's
/// extension and a fixed-size body containing the rendered template. If
/// rendering fails, an `Err` of `Status::InternalServerError` is returned.
impl Responder<'static> for Template {
    fn respond_to(self, req: &Request) -> response::Result<'static> {
        let ctxt = req.guard::<State<ContextManager>>().succeeded().ok_or_else(|| {
            // N.B.: removed some logging for brevity
            Status::InternalServerError
        })?.inner().context();

        let (render, content_type) = self.finalize(&ctxt)?;
        Content(content_type, render).respond_to(req)
    }
}

TL;DR:似乎文档具有误导性。show()当您调用和发送响应时,模板实现完全一样。在这两种情况下,它都会在内部调用finalize(),从而生成String模板的呈现。因此,使用不应该有任何性能损失show()

PS:当前main分支的代码有点变化,但逻辑还是一样的

于 2021-09-11T13:16:01.233 回答