askama
askama copied to clipboard
First thing that's not None or empty
Is there a way to do something like: {{ venue.name or venue.fallback_name }}
So take the first thing that's not None or empty and render that?
Currently I have to do this like so, which is verbose:
{% if !venue.name.is_empty() %}
{{ venue.name }}
{% else %}
{{ venue.google_name }}
{% endif %}
Assuming that name
is Option<T>
(where T
is e.g. String
) and fallback_name
then is String
. Then you can utilize Option
's methods, such as or()
and unwrap_or()
.
So say we have the following struct:
#[derive(Template)]
struct Page {
a: Option<String>,
b: Option<String>,
default: String,
}
Then to be able to render a
otherwise default
, you can do:
{{ a.as_deref().unwrap_or(default.as_str()) }}
If you want to render a
otherwise b
otherwise default
, then you can do:
{{ a.as_deref().or(b.as_deref()).unwrap_or(default.as_str()) }}
Complete Example:
#[derive(Template)]
#[template(
source = "{{ a.as_deref().or(b.as_deref()).unwrap_or(default.as_str()) }}",
ext = "html"
)]
struct Page {
a: Option<String>,
b: Option<String>,
default: String,
}
let pages = [
Page {
a: Some("a".into()),
b: None,
default: "default".into(),
},
Page {
a: None,
b: Some("b".into()),
default: "default".into(),
},
Page {
a: Some("a".into()),
b: Some("b".into()),
default: "default".into(),
},
Page {
a: None,
b: None,
default: "default".into(),
},
];
for page in pages {
println!("{:?}", page.render().unwrap());
}
Which would output:
"a"
"b"
"a"
"default"
An Option can also be used as a single element iterator, and might come in handy with for-else.