How do I write a numeric for
loop in a Django template? I mean something like
for i = 1 to n
Unfortunately, that's not supported in the Django template language. There are a couple of suggestions, but they seem a little complex. I would just put a variable in the context:
...
render_to_response('foo.html', {..., 'range': range(10), ...}, ...)
...
and in the template:
{% for i in range %}
...
{% endfor %}
I tried very hard on this question, and I find the best answer here: (from how to loop 7 times in the django templates)
You can even access the idx!
views.py:
context['loop_times'] = range(1, 8)
html:
{% for i in loop_times %}
<option value={{ i }}>{{ i }}</option>
{% endfor %}
Just incase anyone else comes across this question… I've created a template tag which lets you create a range(...)
: http://www.djangosnippets.org/snippets/1926/
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\n {% endfor %} Produces: 5: Something I want to repeat 7: Something I want to repeat 9: Something I want to repeat
This method supports all the functionality of the standard range([start,] stop[, step])
function
<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)
Usage:
{% 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>
Output
<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>
I'm just taking the popular answer a bit further and making it more robust. This lets you specify any start point, so 0 or 1 for example. It also uses python's range feature where the end is one less so it can be used directly with list lengths for example.
@register.filter(name='range')
def filter_range(start, end):
return range(start, end)
Then in your template just include the above template tag file and use the following:
{% for c in 1|range:6 %}
{{ c }}
{% endfor %}
Now you can do 1-6 instead of just 0-6 or hard coding it. Adding a step would require a template tag, this should cover more uses cases so it's a step forward.
You should use "slice" in template, a example like this:
in views.py
contexts = {
'ALL_STORES': Store.objects.all(),
}
return render_to_response('store_list.html', contexts, RequestContext(request, processors=[custom_processor]))
in store_list.html:
<ul>
{% for store in ALL_STORES|slice:":10" %}
<li class="store_item">{{ store.name }}</li>
{% endfor %}
</ul>
This essentially requires a range
function. A Django feature ticket was raised (https://code.djangoproject.com/ticket/13088) for this but closed as "won't fix" with the following comment.
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.
They have a good point - Templates are supposed to be very simple representations of the view. You should create the limited required data in the view and pass to the template in the context.
This shows 1 to 20 numbers:
{% for i in "x"|rjust:"20"|make_list %}
{{ forloop.counter }}
{% endfor %}
also this can help you: (count_all_slider_objects come from views)
{% for i in "x"|rjust:count_all_slider_objects %}
{{ forloop.counter }}
{% endfor %}
or
{% with counter=count_all_slider_objects %}
{% if list_all_slider_objects %}
{% for slide in list_all_slider_objects %}
{{forloop.counter|add:"-1"}}
{% endfor%}
{% endif %}
{% endwith %}