Skip to content

Conversation

Kijewski
Copy link
Member

@Kijewski Kijewski commented Jul 22, 2025

Jinja, being based on Python, allows using conditional expressions:

{{ "then" if condition else "otherwise" }}

will print "then" if condition is truthy, otherwise "otherwise".

This PR adds the same syntax, with a few restrictions, to Askama:

  • The condition must evaluate to a bool (or a reference to it), same as in {% if .. %}.
  • The else-case can be absent in Jinja, then behaves like else None. For Jinja that makes sense. It renders {{ None }} like an empty string. Askama does not do that: Option<T> can not be rendered for any T; we don't unwrap automatically. So, without automatic unwrapping, I don't see a case when you would want to omit the else-case.

Todo:

  • Update book

@Kijewski
Copy link
Member Author

Kijewski commented Jul 22, 2025

Oops:

$ type cargo
cargo ist ein Alias von »RUSTC_BOOTSTRAP=1 cargo«.

I did not quite get #525 before. :) Wow, that's great!

@Kijewski
Copy link
Member Author

@GuillaumeGomez, so what do you think of this feature? Documentation and UI tests are missing, but the functionality is all there. If you give me a ":+1:" on the feature, I'd add the missing parts.

@GuillaumeGomez
Copy link
Collaborator

GuillaumeGomez commented Jul 23, 2025

I'm not convinced. The syntax is really different compared to the rest. Adding conditional expressions inside the "expression tag" seems a bit too much imo.

I did not quite get #525 before. :) Wow, that's great!

It's just the first step. I'm working on the second step currently and hopefully it'll crazily improve nightly outputs, even if you write stuff like:

#[derive(Template)]
// And other attributes
#[template(src = "{{ x.y }}")]
struct X {
    x: u32,
}

It'll be able to show directly that the x.y part is wrong.

@Kijewski
Copy link
Member Author

Kijewski commented Jul 23, 2025

Actually, I use is pattern all the time in jinja templates. Simple things like {{ "logoff" if user else "login" }}. Of course, you can always write {% if user %}logoff{% else %}login{% endif %}, but it's longer and at least to me it's harder on the eyes.

(At least for templating, I like python's "infix if" better that rust's "prefix if", even without the fact that it's easier to parse.)

@GuillaumeGomez
Copy link
Collaborator

Hum... Well I don't really a strong argument against it either. Is there syntax conflict possibility? That's my main worry here.

@Kijewski
Copy link
Member Author

Only with {% for elem in iterator if condition %}. In Jinja the if is parsed as prefix to the condition. If you want to use an if-expression in the iterator-expression, then you have to surround it with parentheses: {% for elem in (iterator if condition) %}

That's why I introduced Expr::parse_no_if_else(), so it's the same in Askama.

);

compare(
r"{{ a if b else c if d else e }}",
Copy link
Collaborator

@GuillaumeGomez GuillaumeGomez Jul 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is absolutely horrifying for my brain to parse. 🤣

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about this formatting? :)

{{
   a if b else
   c if d else
   e
}}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That doesn't help much, I'm too used to blocks. But it's fine, don't worry. One question though, does this work:

{{ a if b else (c if d else e) }}

?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that does work.

@GuillaumeGomez
Copy link
Collaborator

Thinking some more, does it mean we can have stuff like:

{{ a(x if y else z) }}
{% if (a if x else b) %}

?

@Kijewski
Copy link
Member Author

Yes! Both examples would work.

@GuillaumeGomez
Copy link
Collaborator

I'm very afraid of opening this door. 🤣

@GuillaumeGomez
Copy link
Collaborator

Anyway, I don't any valid argument against this feature, so if you have a use for it and want to add it, then let's go. Please ping me once PR is ready for review with tests and docs. :)

@Kijewski Kijewski force-pushed the pr-if branch 3 times, most recently from ec6d66b to f278964 Compare July 27, 2025 02:47
Jinja, being based on Python, allows using conditional expressions:
```jinja
{{ "then" if condition else "otherwise" }}
```
will print `"then"` if `condition` is truthy, otherwise `"otherwise"`.

This PR adds the same syntax, with a few restrictions, to Askama:

* The condition must evaluate to a `bool` (or a reference to it), same
  as in `{% if .. %}`.
* The else-case can be absent in Jinja, then behaves like `else None`.
  For Jinja that makes sense. It renders `{{ None }}` like an empty
  string. Askama does not do that: `Option<T>` can not be rendered
  for any `T`; we don't unwrap automatically. So, without automatic
  unwrapping, I don't see a case when you would want to omit the
  else-case.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants