Tera模板引擎的用法总结
发布时间: 2025-08-06 04:51
|
作者: xueyusky
|
状态: published
|
更新时间: 2025-08-06 06:04
# 基本设置
## 添加依赖
使用tera,在toml的dependencies中添加:
```toml
[dependencies]
tera = "1.19"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
```
## 初始化Tera
```rust
use tera::{Tera, Context};
// 从目录加载模板
let tera = Tera::new("templates/**/*").unwrap();
// 或者从字符串创建
let mut tera = Tera::default();
tera.add_raw_template("hello", "Hello {{ name }}!").unwrap();
```
# 基本用法
## 1. 简单渲染
```rust
use tera::{Tera, Context};
let mut context = Context::new();
context.insert("name", "世界");
let rendered = tera.render("hello.html", &context).unwrap();
println!("{}", rendered);
```
## 2. 使用结构体数据
```rust
use serde::Serialize;
#[derive(Serialize)]
struct User {
name: String,
age: u32,
email: String,
}
let user = User {
name: "张三".to_string(),
age: 25,
email: "zhangsan@example.com".to_string(),
};
let mut context = Context::new();
context.insert("user", &user);
```
# 模板语法
## 1. 变量输出
```rust
{{ name }}
{{ user.name }}
{{ items.0 }}
{{ name | upper }}
{{ price | round(precision=2) }}
{{ content | safe }}
```
## 2. 条件语句
```rust
{% if user.age >= 18 %}
<p>成年用户</p>
{% elif user.age >= 13 %}
<p>青少年用户</p>
{% else %}
<p>儿童用户</p>
{% endif %}
```
## 3. 循环
```rust
{% for item in items %}
<li>{{ item }}</li>
{% endfor %}
{% for user in users %}
{{ loop.index }}
{{ user.name }}
{% endfor %}
{% for item in items %}
<li>{{ item }}</li>
{% else %}
<p>没有项目</p>
{% endfor %}
```
## 4. 模板继承
```rust
{% block title %}默认标题{% endblock %}
{% block content %}{% endblock %}
{% extends "base.html" %}
{% block title %}子页面标题{% endblock %}
{% block content %}
这是子页面内容
{% endblock %}
```
## 5. 包含模板
```html
<!-- header.html -->
<header>
<h1>网站标题</h1>
</header>
<!-- main.html -->
{% include "header.html" %}
<main>
<p>主要内容</p>
</main>
```
## 6. 常用过滤器
```rust
{{ text | upper }}
{{ text | lower }}
{{ text | title }}
{{ text | length }}
{{ text | truncate(length=10) }}
{{ number | round(precision=2) }}
{{ price | filesizeformat }}
{{ date | date(format="%Y-%m-%d") }}
{{ html_content | safe }}
```
# 高级功能
## 1. 自定义过滤器
```rust
use tera::{Tera, Value, Result as TeraResult};
use std::collections::HashMap;
fn reverse_filter(value: &Value, _: &HashMap) -> TeraResult {
if let Some(s) = value.as_str() {
Ok(Value::String(s.chars().rev().collect()))
} else {
Err("过滤器只能用于字符串".into())
}
}
let mut tera = Tera::new("templates/**/*").unwrap();
tera.register_filter("reverse", reverse_filter);
```
## 2. 自定义函数
```rust
use tera::{Tera, Value, Result as TeraResult};
use std::collections::HashMap;
fn get_random_number(_args: &HashMap) -> TeraResult {
use rand::Rng;
let mut rng = rand::thread_rng();
Ok(Value::Number(rng.gen_range(1..=100).into()))
}
tera.register_function("random", get_random_number);
```
## 3. 全局变量
```rust
let mut context = Context::new();
context.insert("site_name", "我的网站");
context.insert("current_year", &2024);
// 或者使用 Tera 的全局变量
tera.register_global_function("now", || {
use chrono::Utc;
Ok(Value::String(Utc::now().format("%Y-%m-%d %H:%M:%S").to_string()))
});
```
# 实际应用示例
## Web应用中的使用
```rust
use tera::{Tera, Context};
use serde::Serialize;
#[derive(Serialize)]
struct Post {
title: String,
content: String,
author: String,
created_at: String,
}
fn render_blog_page(tera: &Tera, posts: Vec) -> String {
let mut context = Context::new();
context.insert("posts", &posts);
context.insert("page_title", "博客首页");
tera.render("blog.html", &context).unwrap()
}
```
## 错误处理
```rust
use tera::{Tera, Context, Error};
fn safe_render(tera: &Tera, template: &str, context: &Context) -> Result {
match tera.render(template, context) {
Ok(rendered) => Ok(rendered),
Err(e) => {
eprintln!("模板渲染错误: {}", e);
Err(e)
}
}
}
```
# 性能优化建议
1. **预编译模板**: 在应用启动时加载所有模板
2. **缓存 Context**: 对于重复使用的数据,考虑缓存 Context
3. **避免复杂逻辑**: 将复杂逻辑放在 Rust 代码中,而不是模板中
4. **使用合适的过滤器**: 选择最适合的内置过滤器而不是自定义