rust web 框架 loco 的后端 HTML 模板

更新日期: 2024-05-05 阅读次数: 300 字数: 731 分类: rust

loco 框架目前的文档还是有点简陋,想通过直接看文档来上手,不太现实。 还是需要自己结合代码去查看三方的依赖库的文档。

目录结构

注意,后台模板及相关的资源文件是在 assets 目录下。 而不是 frontend 目录下,frontend 是 vite 创建的纯前端部分 (前后端分离的方案, loco 的默认首页就是在 frontend 中)。

Loco SaaS 项目,初始化的 assets 目录结构:

> tree assets/

assets/
├── i18n
│   ├── de-DE
│   │   └── main.ftl
│   ├── en-US
│   │   └── main.ftl
│   └── shared.ftl
├── static
│   ├── 404.html
│   └── image.png
└── views
    └── home
        └── hello.html

view

后台 HTML 模板存放在 assets/views 目录下,这点有点像 laravel, 不叫 template,而称之为 view。

Loco Views 分为两类:

  • JSON view: 其实就是 API 接口的 JSON 返回。但是独立到一个文件中进行定义,确实代码简洁了不少。例如,用户接口的 JSON 返回,就定义在了 src/views/user.rs 中。
  • Template view: 这个就是后台 HTML 模板。

但是 Loco Template View 有一点不一样,就是需要先封装在 src/views 中,然后才能在 src/controllers 中使用。 这在之前用过的 web 框架中从未见过,其他框架都是直接在 controller 中使用就行了。

官方的一个示例:

// src/views/dashboard.rs
pub fn home(v: impl ViewRenderer) -> Result<impl IntoResponse> {
    format::render().view(&v, "home/hello.html", json!({}))
}

// src/controllers/dashboard.rs
pub async fn render_home(ViewEngine(v): ViewEngine<TeraView>) -> Result<impl IntoResponse> {
    views::dashboard::home(v)
}

如何传递参数呢?

下面是 github issue 中的一段伪代码:

// controller.rs
render_home(e: Engine<TeraView>) -> Result<impl IntoResponse> {
   views::dashboard::home(e, current_user)
}

// src/views/dashboard.rs
home(e: eng, user: User) -> impl ...{
        format::template(e, "dashboard/home.html", json!(name: user.name))
}

Tera 模板引擎

https://keats.github.io/tera/

A powerful, easy to use template engine for Rust. Inspired by Jinja2 and Django templates.

看来是借鉴了 python 主流 web 框架的模板语法。 看了一下文档, 功能非常强大,不逊色于 django template。

示例:

<title>{% block title %}{% endblock title %}</title>
<ul>
{% for user in users -%}
  <li><a href="{{ user.url }}">{{ user.username }}</a></li>
{%- endfor %}
</ul>

I18N 多语言支持

默认的 hello.html 中包含了一个示例:

<html><body>
  <img src="/static/image.png" width="200"/>
  <br/>
  find this tera template at <code>assets/views/home/hello.html</code>:
  <br/>
  <br/>
  {{ t(key="hello-world", lang="en-US") }},
  <br/>
  {{ t(key="hello-world", lang="de-DE") }}

</body></html>

比较奇怪的是 lang 参数,是否可以省略?

从 view 的配置文件 src/initializers/view_engine.rs 可以看到:

use fluent_templates::{ArcLoader, FluentLoader};

fluent-templates lets you to easily integrate Fluent localisation into your Rust application or library.

https://github.com/XAMPPRocky/fluent-templates

Cargo.toml

# view engine i18n
fluent-templates = { version = "0.8.0", features = ["tera"] }
unic-langid = "0.9.4"
# /view engine

回到正题,是否可以省略 lang,看起来不太容易:

In handlebars, fluent-templates will read the lang field in your handlebars::Context while rendering.

通过模板参数传过去看起来是省不了。

github issue 中有一个相关的讨论,不过目前还没有结论。

https://github.com/loco-rs/loco/pull/389

继续阅读

动手篇:rust web 框架 Loco 新建一个 HTML 页面

参考

  • https://loco.rs/docs/the-app/views/
  • https://keats.github.io/tera/

tags: loco

关于作者 🌱

我是来自山东烟台的一名开发者,有敢兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式