Opened 10 years ago

Closed 10 years ago

Last modified 10 years ago

#3481 closed (wontfix)

request: else part for a for loop or make if to create variable

Reported by: jimmy@… Owned by: Adrian Holovaty
Component: Template system Version:
Severity: Keywords: for if else loop
Cc: Triage Stage: Design decision needed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:


When using the object_detail generic view:

If you have for examle a blog entry Entry(), and comments Comment() on it;
I would use this to loop for comments:

{% for comment in object.comment_set.all %}
   {{ comment.body_text }}
{% endfor%}

Now the problem is; it is impossible to display something in case there are no comments without hitting the database again.

It could be fixed with an '{% elsefor %}' or by making it possible to assign object.comment_set.all to some var once.

Another solution would be to make '{% if object.comment_set_all %}' create a variable 'if.result' or something.

Attachments (1)

for_else.diff (4.2 KB) - added by rodolfo.3@… 10 years ago.
This patch allow a tag "else" in a "for" loop.

Download all attachments as: .zip

Change History (9)

comment:1 Changed 10 years ago by Chris Beaven

Triage Stage: UnreviewedDesign decision needed

It would be good to have {% else %} for {% for %} tags - I know we want to stay away from too much logic, but this is a very common use case and it's not that difficult to understand is it?

comment:2 Changed 10 years ago by Malcolm Tredinnick

It sounds like you are wanting "else" to only be executed when the "for" is not looped through. However, this is not the way it works in, for example, Python ("else" is executed when you don't break out of the loop prematurely). I don't think we want to implement it in a way that is so vastly different from Python: whilst we aren't implementing Python in templates, behaving completely the opposite way is going to be too confusing.

Setting a variable is a slippery slope and not really in the spirit of templates. Fixing #2430 will help a little bit here (the if-test will be faster and memory efficient). Knowing that you are going to be accessing result_set.all() multiple times and passing it in as a QuerySet to the template will help, too (that is the normal and recommended way to do this efficiently at the moment).

There may be another solution available, so I'll leave this open in case another developer has an idea, but I am very much against using "else" in the proposed way; it's just too confusing for Python programmers.

comment:3 Changed 10 years ago by jimmy@…

In the meanwhile, maybe good alternative names would be 'nofor' or just 'none'.

comment:4 Changed 10 years ago by Chris Beaven

Version: 0.95

Yea, silly choice of words there by me. An alternate name like nofor would be a much better choice.

Really, I'm only a +0 on this ticket anyway and was just chiming in while reviewing.

comment:5 Changed 10 years ago by…

Can use the new "with" tag for this.

{% with object.comment_set.all as comment_list %}
{% for comment in comment_list %}
   {{ comment.body_text }}
{% endfor%}
{% endwith %}

comment:6 Changed 10 years ago by jimmy@…

Great! This is a perfect solution!

comment:7 Changed 10 years ago by Baptiste <baptiste.goupil@…>

Resolution: wontfix
Status: newclosed

Since there is a workaround and that no one gave an idea...

Changed 10 years ago by rodolfo.3@…

Attachment: for_else.diff added

This patch allow a tag "else" in a "for" loop.

comment:8 Changed 10 years ago by anonymous

I'm add a patch to allow a tag "else" in a "for" loop. When the list is empty, it is called (as well "else" on a "if"):

{% for i in items %}
  {{ i }}
{% else %}
  no items
{% endfor %}

This is useful?

Note: See TracTickets for help on using tickets.
Back to Top