### {% %}の利用
テンプレート内での計算などができる
<body class="container">
<h1 class="display-6 my-2">{{title}}</h1>
<div class="border border-primary p-3 my-3">
{% set v1 = value * 1.08 %}
{% set v2 = value * 1.1 %}
<p class="my-2">value: {{ value }}</p>
<p class="my-2">value1: {{ v1 }}</p>
<p class="my-2">value2: {{ v2 }}</p>
</div>
</body>
main.rs
#[tokio::main]
async fn main() {
let app = axum::Router::new()
.route("/:value", axum::routing::get(handle_index));
axum::Server::bind(&"192.168.56.10:8000".parse().unwrap())
.serve(app.into_make_service())
.await
.unwrap();
}
async fn handle_index(axum::extract::Path(value):
axum::extract::Path<usize>
)-> axum::response::Html<String> {
let tera = tera::Tera::new("template/*").unwrap();
let mut context = tera::Context::new();
context.insert("title", "Index page");
context.insert("value", &value);
let output = tera.render("index.html", &context);
axum::response::Html(output.unwrap())
}
{% raw %}で生の文を出力する
L HTMLタグはそのまま表示される
<div class="border border-primary p-3 my-3">
{% raw %}
{% set v1 = value * 1.08 %}
{% set v2 = value * 1.1 %}
<p class="my-2">value: {{ value }}</p>
<p class="my-2">value1: {{ v1 }}</p>
<p class="my-2">value2: {{ v2 }}</p>
{% endraw %}
</div>
テキストで繋げる
<div class="border border-primary p-3 my-3">
{% set v1 = value * 1.08 %}
{% set v2 = value * 1.1 %}
<p class="my-2">value: {{ value }}</p>
<p class="my-2">value1: {{ value ~ " * 1.08 = " ~ v1 }}</p>
<p class="my-2">value2: {{ value ~ " * 1.1 = " ~ v2 }}</p>
</div>
### ifを使う
{% if value % 2 == 0 %}
<div class="border border-primary p-3 my-3">
<p class="my-2">value: {{ value ~ "は偶数です。" }}</p>
</div>
{% else %}
<div class="border border-primary p-3 my-3">
<p class="my-2">value: {{ value ~ "は奇数です。" }}</p>
</div>
{% endif %}
更に分岐したい場合
{% if value % 3 == 0 %}
<div class="border border-primary p-3 my-3">
<p class="my-2">value: {{ value ~ "はグーです。" }}</p>
</div>
{% elif value % 3 == 1 %}
<div class="border border-primary p-3 my-3">
<p class="my-2">value: {{ value ~ "はチョキです。" }}</p>
</div>
{% else %}
<div class="border border-primary p-3 my-3">
<p class="my-2">value: {{ value ~ "はパーです。" }}</p>
</div>
{% endif %}
### 繰り返し表示
main.rs
async fn handle_index()-> axum::response::Html<String> {
let data = [
Myform {name:"taro".to_string(), mail:"taro@yamada".to_string()},
Myform {name:"hanako".to_string(), mail:"hanako@flower".to_string()},
Myform {name:"sachiko".to_string(), mail:"sachiko@happy".to_string()},
Myform {name:"jiro".to_string(), mail:"jiro@change".to_string()},
];
let tera = tera::Tera::new("template/*").unwrap();
let mut context = tera::Context::new();
context.insert("title", "Index page");
context.insert("data", &data);
let output = tera.render("index.html", &context);
axum::response::Html(output.unwrap())
}
view
<ul class="list-group">
{% for item in data %}
<li class="list-group-item">
{{item.name}} <{{item.mail}}>
</li>
{% endfor %}
</ul>
### キー&バリューのコレクション
マップにHashMapインスタンスを代入。このHashMapをテンプレート側で処理する
async fn handle_index()-> axum::response::Html<String> {
let mut map = std::collections::HashMap::new();
map.insert("taro", ("taro@yamada", 39));
map.insert("hanako", ("hanako@flower", 28));
map.insert("sachiko", ("sachiko@happy", 17));
let tera = tera::Tera::new("template/*").unwrap();
let mut context = tera::Context::new();
context.insert("title", "Index page");
context.insert("data", &map);
let output = tera.render("index.html", &context);
axum::response::Html(output.unwrap())
}
<ul class="list-group">
{% for key, value in data %}
<li class="list-group-item">
[{{loop.index}}] {{ key }}({{value.1}}) <{{value.0}}>
</li>
{% endfor %}
</ul>
loop.indexは繰り返し情報がまとめられたオブジェクト
### フィルターの利用
フィルターは、あらかじめRust側で定義した関数を使ってテンプレートの表示を変換する機能
フィルター用の関数は形が決まっている
fn 関数(引数1: &value, 引数2: &HashMap)-> Result{…}
作成したフィルター関数はTeraのインスタンスに登録する
main.rs
async fn handle_index()-> axum::response::Html<String> {
let mut tera = tera::Tera::new("template/*").unwrap();
tera.register_filter("hello", hello_filter);
let mut context = tera::Context::new();
context.insert("title", "Index page");
context.insert("name", "山田タロー");
let output = tera.render("index.html", &context);
axum::response::Html(output.unwrap())
}
fn hello_filter(value: &tera::Value,
_: &std::collections::HashMap<String, tera::Value>)
-> tera::Result<tera::Value> {
let s = tera::try_get_value!("hello_filter", "value", String, value);
Ok(tera::Value::String(format!("こんにちは、{}さん!", s)))
}
テンプレート
<div class="alert alert-primary">
<p class="my-2">{{ name | hello}}</p>
</div>
### フィルターでオブジェクトを扱う場合
async fn handle_index()-> axum::response::Html<String> {
let mut tera = tera::Tera::new("template/*").unwrap();
tera.register_filter("sample", sample_filter);
let mut context = tera::Context::new();
context.insert("title", "Index page");
context.insert("id", &1);
let output = tera.render("index.html", &context);
axum::response::Html(output.unwrap())
}
fn sample_filter(value: &tera::Value,
_: &std::collections::HashMap<String, tera::Value>)
-> tera::Result<tera::Value> {
let data = [
("taro", "taro@yamada", 39, "male"),
("hanako", "hanako@flower", 28, "female"),
("sachiko", "sachiko@happy", 17, "female"),
("jiro", "jiro@change", 6, "male")
];
let n = tera::try_get_value!("sample_filter", "value", usize, value);
let item = data[n];
Ok(tera::Value::String(format!("{}({},{})<{}>", item.0, item.3, item.2, item.1)))
}
### フィルターの属性を利用する
async fn handle_index()-> axum::response::Html<String> {
let mut tera = tera::Tera::new("template/*").unwrap();
tera.register_filter("calc", calc_filter);
let mut context = tera::Context::new();
context.insert("title", "Index page");
let output = tera.render("index.html", &context);
axum::response::Html(output.unwrap())
}
fn calc_filter(_: &tera::Value,
map: &std::collections::HashMap<String, tera::Value>)
-> tera::Result<tera::Value> {
let price = map.get("price").unwrap().as_f64().unwrap();
let tax = map.get("tax").unwrap().as_f64().unwrap();
let res = price * tax;
Ok(tera::Value::String(format!("price:{} * tax:{} = {}", price, tax, res)))
}
<div class="alert alert-primary">
<p class="my-2">{{ false | calc(price=1234, tax=1.1) }}</p>
</div>