I have been using django with great pleasure and there is a slight
extension to the {% for ... in ... %} default tag I would like to
propose.
I find it useful to have the {% for %} tag syntax extended so that one
can write:
{% for a,b in L %} meaning the obvious thing
Also (maybe more contentious):
{% for i in L1,L2 %} meaning what one would write in python as:
for i in zip(L1,L2)
It is actually a trivial patch to the original ForNode and do_for in
django.template.defaulttags.py to extend {% for ... %} so that it
would accept anything of the form
{% for a_1,a_2,...,a_k in L %} (implying that L is a list of k-uples)
or
{% for a in L1,L2,...,L_n %} (then at each iteration, a will be an n-
uple)
or
{% for a_1,a_2,...a_k in L_1,L_2,...,L_k %} (where each a_i iterates
over L_i in 'parallel')
Provided that no space is allowed between commas and variables (i.e.
a,b NOT a, b) the modification is very simple (only 4 or 5 lines to be
changed). But I have noticed this sort of restriction is already in
place for other tags such as {% cycle ... %} so it would not be an
issue.
This new 'for' does not actually process data, just rearranges them so
that they correspond better to the desired layout. This would allow
transfering some such manipulations from views to templates where I
feel they belong more naturally.
If there is an interest for this I can provide the patch and follow
what procedure is customary for django (which I am not familiar with
yet ;)
--
Arnaud
You can do this. a,b return type is implicitly (a,b) in Python. In
other words:
{% for x in L %}
{{ x.0 }}
{{ x.1 }}
{% endfor %}
> Also (maybe more contentious):
> {% for i in L1,L2 %} meaning what one would write in python as:
> for i in zip(L1,L2)
This is starting to look like more logic in the template than you
would normally use. I think the idea of the {% for %} tag has been
(and should be) to be able to easily cycle through collections of data
you've already set up. Most of the time you don't have to manipulate
them in any way other than how you've collected the data in the first
place. If you *DO* need to manipulate them, you should use views, not
templates.
You can also write your own tag to do the same - however, I still
think the work should be done in the view.
My .02
-rob
+1
>
> You can do this. a,b return type is implicitly (a,b) in Python. In
> other words:
> {% for x in L %}
> {{ x.0 }}
> {{ x.1 }}
> {% endfor %}
well yes, but you have to admit that
{% for name, description in list %}
{{ name }} - {{ description }}
{% endfor %}
looks way better ;)
just some syntax sugar, but I think it's actually useful
>
> > Also (maybe more contentious):
> > {% for i in L1,L2 %} meaning what one would write in python as:
> > for i in zip(L1,L2)
+0 - I like this feature, but I didn't know when I first looked at it
whether its a zip() or concatenation, that should be clear
>
> This is starting to look like more logic in the template than you
> would normally use. I think the idea of the {% for %} tag has been
> (and should be) to be able to easily cycle through collections of data
> you've already set up. Most of the time you don't have to manipulate
> them in any way other than how you've collected the data in the first
> place. If you *DO* need to manipulate them, you should use views, not
> templates.
>
> You can also write your own tag to do the same - however, I still
> think the work should be done in the view.
well, I can see a use case for this - if you want to iterate over
multiple lists at a time... for example if you want to render
something to columns rather that rows in a table, that's a change that
shouldn't require a change to the view function, yet it is near
impossible to achieve withou custom filters or tags...
>
> My .02
and mine ;)
> -rob
>
>
> >
>
--
Honza Král
E-Mail: Honza...@gmail.com
ICQ#: 107471613
Phone: +420 606 678585
> On 2/17/07, oggie rob <oz.rob...@gmail.com> wrote:
>>
>>> I find it useful to have the {% for %} tag syntax extended so
>>> that one can write:
>>> {% for a,b in L %} meaning the obvious thing
>
> +1
>
>>
>> You can do this. a,b return type is implicitly (a,b) in Python. In
>> other words:
>> {% for x in L %}
>> {{ x.0 }}
>> {{ x.1 }}
>> {% endfor %}
>
> well yes, but you have to admit that
> {% for name, description in list %}
> {{ name }} - {{ description }}
> {% endfor %}
> looks way better ;)
> just some syntax sugar, but I think it's actually useful
If you change the tuples into dictionaries in the view, you can get
the same kind of clarity (and that's what I find myself doing quite a
bit, actually):
{% for x in L %}
{{ x.name }}
{{ x.description }}
{% endfor %}
Todd
On Feb 17, 9:48 pm, "oggie rob" <oz.robhar...@gmail.com> wrote:
> > I find it useful to have the {% for %} tag syntax extended so that one can write:
> > {% for a,b in L %} meaning the obvious thing
>
> You can do this. a,b return type is implicitly (a,b) in Python. In
> other words:
> {% for x in L %}
> {{ x.0 }}
> {{ x.1 }}
> {% endfor %}
You can do this of course but it does not help to make sense of the
template. E.g.
{% for key,value in L %}
{{ key }}->{{ value }}
{% endfor %}
looks neater than
{% for key_value in L %}
{{ key_value.0 }}->{{ key_value.1 }}
{% endfor %}
[...]
> This is starting to look like more logic in the template than you
> would normally use. I think the idea of the {% for %} tag has been
> (and should be) to be able to easily cycle through collections of data
> you've already set up. Most of the time you don't have to manipulate
> them in any way other than how you've collected the data in the first
> place. If you *DO* need to manipulate them, you should use views, not
> templates.
Following this argument there is no need for {% for ... in L reversed
%} as L can be reversed in the view :)
Here is an example:
IMHO which way round a table is displayed shouldn't really be the
concern of the view but rather of the template. Due to the nature of
HTML (where a table essentially is a list of rows) the current form of
{% for ... %} forces this *layout* decision to take place in the view
unless one writes a custom tag.
Of course this is a more general problem that my suggestion does not
solve completely but it has helped me in some cases to move layout
decisions from views to templates.
--
Arnaud
Yes I found myself doing that a lot too until I thought I'd done it
enough times :)
This is one of the motivations for me to change this : to get clarity
in the template without extra code in the view (code which is only
shuffling around data structures to make them fit with the {% for ...
%} tag
> Todd
--
Arnaud
Yes, however you're looking at the case of only two variables. Think
of how unmanageable it will start to look like this:
{% for name,description,value,href in L %}...
It is better to get a dict back from the view instead of creating one
in the template.
-rob
+1 from me, too. Nicer than the current idiom.
--
Jeff Bauer
Rubicon, Inc.
+1
The {{ x.0 }} syntax is simply ugly and unreadable.
> > > Also (maybe more contentious):
> > > {% for i in L1,L2 %} meaning what one would write in python as:
> > > for i in zip(L1,L2)
>
> +0 - I like this feature, but I didn't know when I first looked at it
> whether its a zip() or concatenation, that should be clear
+0
For the same reason Honza mentioned. I would be ok with introducing
"zip" in there though:
{% for i in zip L1,L2 %}
+1
> Also (maybe more contentious):
> {% for i in L1,L2 %} meaning what one would write in python as:
> for i in zip(L1,L2)
+0
--
I like python!
UliPad <<The Python Editor>>: http://wiki.woodpecker.org.cn/moin/UliPad
My Blog: http://www.donews.net/limodou
+1.
> > Also (maybe more contentious):
> > {% for i in L1,L2 %} meaning what one would write in python as:
> > for i in zip(L1,L2)
Most people seem to be +0 on this, but I'm very much -1.
Firstly, the proposed syntax reads to me as 'iterate over concatenated
list', not 'iterate over zipped list'
Secondly, remember that one of the audiences of the template language
is designers with no programming experience. IMHO, adding operational
modes to template tags in this way only serves to complicate what
needs to be a simple interface.
However - I acknowledge the use case: Two lists, n items long, that
are from independent sources. I think a separate template tag in the
same vein as {% regroup %} would be a better approach.
{% zip lista listb as combined %}
{% for a,b in combined %}
...
This would be easier to explain, unambiguous, and doesn't pollute the
simplicity of the for tag.
Yours,
Russ Magee %-)
On Feb 18, 6:54 am, "Russell Keith-Magee" <freakboy3...@gmail.com>
wrote:
[...]
> > > Also (maybe more contentious):
> > > {% for i in L1,L2 %} meaning what one would write in python as:
> > > for i in zip(L1,L2)
>
> Most people seem to be +0 on this, but I'm very much -1.
>
> Firstly, the proposed syntax reads to me as 'iterate over concatenated
> list', not 'iterate over zipped list'
This is what people have remarked on and I agree.
> Secondly, remember that one of the audiences of the template language
> is designers with no programming experience. IMHO, adding operational
> modes to template tags in this way only serves to complicate what
> needs to be a simple interface.
I find this argument powerful. However I am still willing to defend
the idea a bit :)
> However - I acknowledge the use case: Two lists, n items long, that
> are from independent sources. I think a separate template tag in the
> same vein as {% regroup %} would be a better approach.
>
> {% zip lista listb as combined %}
> {% for a,b in combined %}
This is definitely much better than my initial suggestion.
OTOH we could also add an optional 'zipped' keyword at the end (just
like 'reversed'):
{% for a,b in A,B zipped %} would be easier to interpret IMHO
To recap I now put forward the following, given that x can be a
variable or a comma-separated list of variables (i.e. a or a,b or
a,b,c ...)
1. {% for x in L %}
meaning: for x in L
example: {% for a,b in L %} to extract values from a list of pairs
2. {% for x in A,B[,C...] zipped %}
meaning: for x in zip(A,B[,C...])
example: {% for a,b in A,B zipped %} to extract values from 2 lists in
parallel
This idiom looks clear to me. However I am not a non-programmer ;)
3. {% for x in L zipped %}
meaning: for x in zip(*L)
example: given that table = [ row1, row2, ... ], each row being a
sequence of items.
{% for col in table zipped %} to iterate over the columns of 'table'
rather than the rows.
If people think 1. is good but 2. and 3. are confusing I will be glad
to submit a patch for 1. only. As someone pointed out I can always
have my own custom tags.
then to obtain the same functionality as 2. and 3. one could have as
suggested by Russell above:
2'. {% zip A,B[, C] as ABC %}
3', {% zip table as transposed %}
--
Arnaud
On Feb 18, 10:10 pm, "Arnaud Delobelle" <arno...@googlemail.com>
wrote:
> > However - I acknowledge the use case: Two lists, n items long, that
> > are from independent sources. I think a separate template tag in the
> > same vein as {% regroup %} would be a better approach.
>
> > {% zip lista listb as combined %}
> > {% for a,b in combined %}
I prefer using filters for this sort of thing:
{% for a,b in lista|zip:listb %}
{% endfor %}
Regarding the main part of this post (unpacking of lists in a for
tag), I'm surprised no-one has created a ticket yet!
Here it is now: http://code.djangoproject.com/ticket/3523
I added a simple patch for that... it definitely needs improvement -
!!!! it will break current templates if it remains as is !!!! (a
single loopvar must be handled as a special case - simple change) and
it's not very verbose in it's error messages...
but assuming you treat it nicely, could you test it and verify it's
the thing you wanted? I will the polish the thing up a bit.
thanks