Django模板中的数字for循环


Answers:


392

我使用了一种简单的技术,该技术非常适合没有特殊标签且没有其他上下文的小情况。有时候这很方便

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

9
FWIW,012 == 12,所以它只会遍历1和2
詹森

22
{%为我在“0123456789” | make_list%}遍历所有10个,而不是跳过0
里克

7
生成带有“ rjust”的任意长度的字符串{% for i in "x"|rjust:"100" %}
Aaron

27
第三次,这个答案很糟糕。不要使用这个。使用模板标记并正确执行。我看不出答案是不好的,足以删除评论。
Rebs

6
@Rebs这有什么不好?当然,这是很麻烦的,但是仅仅因为您需要在项目中的小范围内循环一次而添加模板标签也不是一个很好的解决方案。
tobltobs

114
{% with ''|center:n as range %}
{% for _ in range %}
    {{ forloop.counter }}
{% endfor %}
{% endwith %}

9
好答案。之所以有效,是因为center创建了由n个空格组成的字符串,然后将其循环。然后将忽略每个空格字符,但是可以从forloop.counter(或forloop.counter0)中找到range中的当前值。见docs.djangoproject.com/en/dev/ref/templates/builtins/#center
isedwards

2
好答案!不必创建新的过滤器。
米格尔·艾克

无需采取任何措施。优秀的黑客
穆罕默德谢里夫ç

106

不幸的是,Django模板语言不支持该功能。有一对夫妇建议,但他们似乎有点复杂。我只是将变量放在上下文中:

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

并在模板中:

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

13
Django的作者禁止在模板中使用纯Python的动机似乎毫无意义且无关紧要,与不使用它的痛苦和浪费的时间相比,更不用说当真棒了(Python! )已经在那里!
Bogatyr

2
@Bogatyr如果您要的是,只需使用Jinja2:docs.djangoproject.com/en/1.9/topics/templates/…–
tghw

78

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

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

您将使用以下代码:

{% load my_filters %}
{% for i in 15|times %}
    <li>Item</li>
{% endfor %}

1
我认为这是正确的解决方案。不要range(1, 16)让数从1开始,而不是0
chhantyal

还要在templatetags目录中创建一个空文件_ init _.py。还将这些行添加到my_filters.pyfrom django.template import Library;register = Library()
Ajeeb.KP

添加第二个过滤器参数,您将获得python内置的完整范围函数。@register.filter(name='range') def filter_range(start, end): return range(start, end)然后用作{% for i in 1|range:6 %}{% endfor %}。查看全部回答以下....
保罗Kenjora

我改变了这种略显(原谅格式化): try: return range(number) except: return []。这样,它永远不会引发错误并返回空数组(类似于大多数模板函数的工作方式)。
Tim Tisdall


41

您可以通过绑定

{'n' : range(n) }

到模板,然后执行

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

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

(已更新,以实现Python3兼容性)


1
使用range(n)在Python 3,如果我没有记错的话,x范围是不推荐它
费利西奥

完全同意。那是我将应用程序转换为Python3时必须碰到的两行代码之一。
Dave W. Smith

9

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


9

以防万一其他人遇到这个问题……我创建了一个模板标记,可让您创建一个range(...)http : //www.djangosnippets.org/snippets/1926/

接受与“范围”内置参数相同的参数,并创建一个包含以下内容的列表
“范围”的结果。

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

例如:
    {%mkrange 5 10 2 as some_range%}
    {%for some inrange_range}
      {{i}}:我想重复的\ n
    {%endfor%}

产生:
    5:我想重复一遍 
    7:我想重复一遍 
    9:我想重复的事情


1
-1支持Alex Pi的代码片段,该代码片段增加了对可变参数的支持。
m000 2012年

9

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

您甚至可以访问idx!

views.py:

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

的HTML:

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

9

您可以通过:

{'n':range(n)}

使用模板:

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


可读,简单,易于理解,如果您是下一个维护代码的人,会发生什么情况
rossdavidh

7

您应该使用“ 切片模板”,像这样的例子:

在views.py中

contexts = {
    'ALL_STORES': Store.objects.all(),
}

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

在store_list.html中:

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

1
不确定这是否是OP所寻找的,但这正是我所寻找的。=)
GChorn 2014年

7

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

<app>/templatetags/range.py

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)

用法:

{% 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>

输出量

<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>

您的解决方案不起作用for value in 0|range:"10,2"。您必须按以下步骤更改代码:args = filter(lambda x: isinstance(x, int) and x >= 0, (_min, _max, _step))
Bedilbek

@Bedilbek此代码模仿标准python范围。即使没有明确的step参数,它也不支持负范围。>>> list(range(10,2))[] >>> list(range(10,2,-1))[
10、9、8、7、6、5、4、3

5

我只是进一步扩大了流行的答案,并使其更加可靠。这使您可以指定任何起点,例如0或1。它还使用python的range功能,其中末尾少了一个,因此可以直接用于列表长度。

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

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

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

现在,您可以执行1-6而不是仅执行0-6或对其进行硬编码。添加一个步骤将需要一个模板标记,这应该涵盖更多的用例,因此这是向前迈出的一步。


这是@ guillermo-siliceo-trueba答案的扩展。
保罗·肯乔拉

5

这本质上需要一个range功能。为此,提出了Django功能票证(https://code.djangoproject.com/ticket/13088),但由于“无法修复”而关闭,并带有以下注释。

我对这个想法的印象是,它试图导致在模板中进行编程。如果您有需要呈现的选项列表,则应在视图中而不是模板中进行计算。如果那只是一个值范围那么简单,那就去吧。

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


6
视图应用于数据,模板应用于表示。视图不应要求了解模板的内容,尤其是范围。Django忽略这些功能请求的原因完全是垃圾。
Rebs

3

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


1
您能否提供一个示例/说明其工作原理?
Rebs

1

对于那些寻求简单答案的人,只需要显示一定数量的值,例如,假设100个帖子中有3个只是{% for post in posts|slice:"3" %}正常添加和循环,则只会添加3个帖子。


0

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

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

2
不知道您为什么不赞成投票,这是一个有效的答案。与上面提供的实现适当的过滤器相比,我不喜欢这种解决方案。数据库模型应保持精简。但这仍然比大多数人接受的答案要好。
Rebs

我什至不知道……
阿尔珀(Alper)

我来晚了9年,但我赞成您加入家族,甚至不用担心。
萨希尔

-5
{% for i in range(10) %}
   {{ i }}

{% endfor %}

尽管此代码可以回答问题,但提供有关此代码为何和/或如何回答问题的其他上下文,可以提高其长期价值。
xiawi
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.