Django模板中的循环数字

Numeric for loop in Django templates

如何在Django模板中编写数字for循环? 我的意思是

1
for i = 1 to n

我使用了一种简单的技术,适用于没有特殊标签且没有其他上下文的小案例。有时这会派上用场

1
2
3
{% for i in '0123456789'|make_list %}
    {{ forloop.counter }}
{% endfor %}


不幸的是,Django模板语言不支持。有一些建议,但它们看起来有点复杂。我只想在上下文中放一个变量:

1
2
3
...
render_to_response('foo.html', {..., 'range': range(10), ...}, ...)
...

并在模板中:

1
2
3
{% for i in range %}
     ...
{% endfor %}


1
2
3
4
5
{% with ''|center:n as range %}
{% for _ in range %}
    {{ forloop.counter }}
{% endfor %}
{% endwith %}


我对这个问题的看法,我认为是最好的。我在templatetags目录中保留了my_filters.py。

1
2
3
@register.filter(name='times')
def times(number):
    return range(number)

你会这样使用:

1
2
3
4
5
6
7
8
{% load my_filters %}
{% for i in 15|times %}
   
<li>
Item
</li>

{% endfor %}


也许是这样的?

1
2
3
{% for i in"x"|rjust:"100" %}
...
{% endfor %}

你可以通过绑定

1
{'n' : range(n) }

到模板,然后做

1
2
3
{% for i in n %}
...
{% endfor %}

请注意,您将获得从0开始的行为(0,1,... n-1)。

(针对Python3兼容性进行了更新)


你没有传递n本身,而是传递range(n) [从0到n-1的整数列表],从你的视图到你的模板,在后者你做{% for i in therange %}(如果你绝对坚持在基于1而不是正常的基于0的索引上,您可以在循环体中使用forloop.counter ;-)。


只是想让其他人遇到这个问题...我已经创建了一个模板标签,可以让你创建一个range(...):http://www.djangosnippets.org/snippets/1926/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Accepts the same arguments as the 'range' builtin and creates a list containing
the result of 'range'.

Syntax:
    {% mkrange [start,] stop[, step] as context_name %}

For example:
    {% mkrange 5 10 2 as some_range %}
    {% for i in some_range %}
      {{ i }}: Something I want to repeat

    {% endfor %}

Produces:
    5: Something I want to repeat
    7: Something I want to repeat
    9: Something I want to repeat


此方法支持标准range([start,] stop[, step])函数的所有功能

<5233>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from django import template

register = template.Library()


@register.filter(name='range')
def _range(_min, args=None):
    _max, _step = None, None
    if args:
        if not isinstance(args, int):
            _max, _step = map(int, args.split(','))
        else:
            _max = args
    args = filter(None, (_min, _max, _step))
    return range(*args)

用法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{% load range %}

<p>
stop 5
{% for value in 5|range %}
{{ value }}
{% endfor %}

</p>

<p>
start 5 stop 10
{% for value in 5|range:10 %}
{{ value }}
{% endfor %}

</p>

<p>
start 5 stop 10 step 2
{% for value in 5|range:"10,2" %}
{{ value }}
{% endfor %}

</p>

产量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<p>
stop 5
0 1 2 3 4

</p>

<p>
start 5 stop 10
5 6 7 8 9

</p>

<p>
start 5 stop 10 step 2
5 7 9

</p>

我在这个问题上非常努力,我在这里找到了最好的答案:
(从如何在django模板中循环7次)

你甚至可以访问idx!

views.py:

1
context['loop_times'] = range(1, 8)

HTML:

1
2
3
{% for i in loop_times %}
        <option value={{ i }}>{{ i }}</option>
{% endfor %}

您应该在模板中使用"切片",例如:

在views.py中

1
2
3
4
5
contexts = {
    'ALL_STORES': Store.objects.all(),
}

return render_to_response('store_list.html', contexts, RequestContext(request, processors=[custom_processor]))

在store_list.html中:

1
2
3
4
5
6
7
8
9
<ul>

{% for store in ALL_STORES|slice:":10" %}
    <li class="store_item">{{ store.name }}
</li>

{% endfor %}

</ul>


你可以通过:

{'n':range(n)}

要使用模板:

{%for i in n%}
...
{%endfor%}


我只是进一步采用流行的答案,使其更加强大。这允许您指定任何起始点,例如0或1。它还使用了python的范围功能,其末端较少,因此可以直接使用列表长度。

1
2
3
@register.filter(name='range')
def filter_range(start, end):
  return range(start, end)

然后在您的模板中只包含上面的模板标记文件并使用以下内容:

1
2
3
{% for c in 1|range:6 %}
{{ c }}
{% endfor %}

现在你可以做1-6而不只是0-6或硬编码。添加一个步骤需要一个模板标签,这应该涵盖更多的用例,因此它是向前迈出的一步。


您可以使用:
{% with ''|center: i as range %}


这基本上需要range功能。为此提出了一个Django功能票(https://code.djangoproject.com/ticket/13088),但关闭了"将无法修复"以及以下注释。

My impression of this idea is that it is trying to lead to programming in the template. If you have a list of options that need to be rendered, they should be computed in the view, not in the template. If that's as simple as a range of values, then so be it.

他们有一个好点 - 模板应该是视图的非常简单的表示。您应该在视图中创建有限的必需数据,并在上下文中传递给模板。


如果数字来自模型,我发现这是该模型的一个很好的补丁:

1
2
def iterableQuantity(self):
    return range(self.quantity)