askama
askama copied to clipboard
Tuple support
This feature would really improve on the fly restructuring of option<> data in tuples in order to match them more efficient.
It has been mentioned before, but not been implemented yet.
Was this issue solely about indexing and destructuring? Because if so, then it can be closed.
Unless, this issue also implicitly asks for support of e.g.
{% let x = ("foo", "bar") %}
?
Originally posted by @vallentin in https://github.com/djc/askama/issues/47#issuecomment-756037759
Can you write up a more specific example of what you're looking for?
[...] in order to match them more efficient
Do you have a more concrete example of what you need this for?
That said, I've encountered the need a few times as well. I needed it more for being able to construct tuples from other variables. To be able to call functions taking tuples.
Sorry, took a little, gotta learn for exams.
I have encountered it a few times now, consider having a few optional variables, e.g. from different places in a given struct. The code should behave differently depending on if zero, one or both of them are not None.
In usual rust this would not be a problem, you'd use match
to take a tuple you build of the variables you're interested in.
Building tuples like described is no problem in jinja either, I think.
But if I try to create these in askama templates, I run into an error.
Sorry, took a little, gotta learn for exams.
No need to say sorry, we're not in a hurry. Take all the time you need :)
The code should behave differently depending on if zero, one or both of them are not None.
So in actuality, isn't your example more something like this then?
(It of course also includes constructing tuples, just looking for a clear example).
{% let x = (Some("foo"), Some("bar")) %}
Since you mention matching, does that mean you'd also want something like this to be supported:
{% match x %}
{% when (Some, Some) with (a, b) %}
{{ a }} {{ b }}
{% when (Some, None) with (a, _) %}
{{ a }} None
{% else %}
Something else
{% endmatch %}
Because that's also not currently supported.
Hey there, that was pretty much my intention, though I tried it like this:
{% when Some with (a, b) %}
where I expected Some to represent the tuple; but looking at it, your vision would be better.
I think your draft sums it up pretty well.
Alright great, that cleared it up for me :)
It's on the border, of allowing more and more logic in templates. Not that I'm against it as being supported.
@djc what do you think about adding tuple construction and extending matching?
Oof, {% when (Some, Some) with (a, b) %}
looks pretty ugly, not to even speak of {% when (Some, None) with (a, _) %}
. I'm not sure something like this fits in well with the current syntax. We could possibly rethink the syntax or just declare this out of scope for the template language.
I was just following the existing semantics. Every time (rarely) I have to use match
in Askama, it always ends up confusing me. Something about the when ... with ...
confuses me.
I would prefer changing it more into something closer to Rust, i.e. use pattern. So instead of {% when Some with (a) %}
then {% when Some(a) %}
. While for the hypothetical {% when (Some, Some) with (a, b) %}
, then it would just be {% when (Some(a), Some(b)) %}
.
Not suggesting all patterns should be supported. But something closer to Rust's semantics, would greatly improve match
es in Askama (in my oppinion).
Though it would require a bit of an overhaul, and if we don't want to maintain both versions, then we can't avoid breaking change either.
Yeah, I decided to take this direction because I wanted to avoid implementing a parser for all of Rust's pattern matching, but maybe that wasn't such a great decision after all. Redoing this would require a bunch of design work IMO, figuring out what to support and what not to support and where a natural boundary would be.
I'd like to show support for this. SeaQL/sea-orm is a very strong project contending for Rust ORM and the way their system provides data with left joins looks like this. How I can access both the first model (representing a post) and the second model (representing the ugc) in an Askama template is beyond me. I figure I could break it apart in to two Vec<>
s, but then I'd have the issue of not being able to pull data from the second Vec<>
as the for loop provides no index and as far as I can see the templating engine provides no way to pull data at specific indexes.
[
(
Model {
id: 1,
thread_id: 1,
ugc_id: 1,
user_id: None,
created_at: 2021-12-02T18:54:24.009344,
},
Some(
Model {
id: 1,
ugc_id: 1,
ip_id: None,
user_id: None,
created_at: 2021-12-02T18:54:23.993207,
content: Some(
"test content",
),
},
),
),
]
After looking into this for a few hours today I've actually come to the conclusion that a Backend <-> Frontend API struct like this may be the better solution. These are assembled manually and passed as a Vec<> to the templater.
pub struct PostForTemplate {
pub id: i32,
pub thread_id: i32,
pub ip_id: Option<i32>,
pub ugc_id: i32,
pub user_id: Option<i32>,
pub created_at: chrono::NaiveDateTime,
pub updated_at: chrono::NaiveDateTime,
pub content: Option<String>,
}
I'm not sure what you tried but I'm pretty sure there are ways to access the data in the tuple form, too.