Opened 9 years ago

Closed 8 years ago

Last modified 6 years ago

#5172 closed (wontfix)

Extend the {% for %} tag to work as a simple loop

Reported by: Chris Beaven Owned by: nobody
Component: Template system Version:
Severity: Keywords: for-tag enhancement feature
Cc: me@…, danielcristian@… Triage Stage: Design decision needed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

It's come up several times in IRC that people wanted to be able to just do a simple loop (repeat this X times) in their template.

The attached patch extends the {% for %} tag so it can also work like this:

{% for 5 %}
repeat me
{% endfor %}

It also works with integer variables and the forloop variable is still available within the loop:

{% for my_integer %}
loop: {{ forloop.counter }}
{% endfor %}

Attachments (2)

simple-for.patch (6.0 KB) - added by Chris Beaven 9 years ago.
numerical-foo-loop.diff (5.6 KB) - added by Vincent Foley 9 years ago.

Download all attachments as: .zip

Change History (16)

Changed 9 years ago by Chris Beaven

Attachment: simple-for.patch added

comment:1 Changed 9 years ago by Chris Beaven

Triage Stage: UnreviewedDesign decision needed

Tests and docs included, just need a decision.

comment:2 Changed 9 years ago by Adrian Holovaty

Hmm, this one merits some discussion. I like the general idea but need to mull over the syntax.

comment:3 Changed 9 years ago by Philippe Raoult

Keywords: feature added

Changed 9 years ago by Vincent Foley

Attachment: numerical-foo-loop.diff added

comment:4 Changed 9 years ago by Vincent Foley

Needs documentation: set

I added a patch of my own. It's more complex than SmileyChris' and needs documentation (and possibly more tests.) Let me know what you think of the general syntax. The patch is attached.

Example usage:

{% for i 1 to 5 %}
    {{ i }}
{% endfor %}

{% for i 1 to 5 by 2 exclusive %}
    {{ i }}
{% endfor %}

{% for i 5 to 1 by -2 %}
    {{ i }}
{% endfor %}

comment:5 Changed 9 years ago by anonymous

Ugh, I don't like at all, sorry gnuvince. The aim isn't to make Django templates into python...

comment:6 Changed 9 years ago by durdinator

Cc: me@… added

Why a significant syntax change instead of a one-liner filter?

@register.filter
def times(count):
    return range(int(count))
{% for item in 5|times %}
  repeat me
{% endfor %}

comment:7 in reply to:  6 Changed 9 years ago by Chris Beaven

Replying to durdinator:

Why a significant syntax change instead of a one-liner filter?

Because it looks simpler (and it's a syntax extension, really) and because then you're stuck with a pointless item context var.

Neither of which are convincing arguments. And talking about this at sprint, it seemed like the core would just prefer to have a new filter named something separate anyway so I don't hold much hope for my patch really :)

comment:8 Changed 9 years ago by Vincent Foley

How about something like:

{% times 5 %}
    {{ times.iter0 }}
    {{ times.iter1 }}
    <br />
{% endtimes %}

# Output
0 1
1 2
2 3
3 4
4 5

comment:9 Changed 9 years ago by Vincent Foley

P.S.: times is just a tentative name. I think repeat would be better.

comment:10 Changed 9 years ago by Chris Beaven

And that's why I like it attached to {% for %} - then you get all of the forloop context variable goodness for free.

comment:11 Changed 9 years ago by Jacob

Resolution: wontfix
Status: newclosed

I just can't come up with a use case that isn't something better done in a view or better done by just writing out the rows by hand. Besides, this is a pretty simple thing to add as a custom tag in your app.

comment:12 Changed 8 years ago by danielcristian

Cc: danielcristian@… added
Resolution: wontfix
Status: closedreopened

I had this model:

class Mana(models.Model):
    name = models.CharField(u'Mana', max_length=200, unique=True)
    image = models.ImageField(u'Symbol', upload_to='manas/')

class Cost(models.Model):
    card = models.ForeignKey(Card)
    quantity = models.IntegerField('Quantity', max_length=2)
    mana = models.ForeignKey(Mana, related_name=u'mana', verbose_name=u'Mana')

(Yes, it's related to Magic Cards...)

Some cards had a cost with a quantity value (1 Forest, 3 Islands, 5 Mountains), and I need to loop quantity times to show n-times the image cost.

It could be done with this kind of loop.

comment:13 Changed 8 years ago by James Bennett

Resolution: wontfix
Status: reopenedclosed

Please do not reopen a ticket that's been marked "wontfix" by a core developer; if you strongly disagree, consider starting a discussion on the developers' mailing list.

comment:14 in reply to:  11 Changed 6 years ago by anonymous

Has patch: unset
Needs documentation: unset
Version: SVN

Replying to jacob:

I just can't come up with a use case that isn't something better done in a view or better done by just writing out the rows by hand. Besides, this is a pretty simple thing to add as a custom tag in your app.

This ticked is old, but to present you with a scenario that I'm into right now: I need to create a varying number of radiobuttons, depending of the number of choices allowed by the parents settings. The parent has a "number of objects allowed" field in the model. I therefore need to repeat a tag that can do the same thing {% for %}, but not iterating over an array or set, but just a variable number.

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