Respuestas:
He usado una técnica simple que funciona bien para casos pequeños sin etiquetas especiales y sin contexto adicional. A veces esto es útil.
{% for i in '0123456789'|make_list %}
{{ forloop.counter }}
{% endfor %}
{% for i in "x"|rjust:"100" %}
{% with ''|center:n as range %}
{% for _ in range %}
{{ forloop.counter }}
{% endfor %}
{% endwith %}
Desafortunadamente, eso no es compatible con el lenguaje de plantilla Django. Hay un par de sugerencias , pero parecen un poco complejas. Simplemente pondría una variable en el contexto:
...
render_to_response('foo.html', {..., 'range': range(10), ...}, ...)
...
y en la plantilla:
{% for i in range %}
...
{% endfor %}
Mi opinión sobre este tema, creo que es la mejor. Mantengo my_filters.py en el directorio templatetags.
@register.filter(name='times')
def times(number):
return range(number)
Y usarías así:
{% load my_filters %}
{% for i in 15|times %}
<li>Item</li>
{% endfor %}
range(1, 16)
obtener números a partir del 1, no del 0.
from django.template import Library;register = Library()
@register.filter(name='range') def filter_range(start, end): return range(start, end)
Luego se acostumbra como {% for i in 1|range:6 %}{% endfor %}
. Vea la respuesta completa a continuación ...
try: return range(number) except: return []
. De esa manera, nunca genera un error y devuelve una matriz vacía (similar a cómo funciona la mayoría de las funciones de plantilla).
Tal vez así?
{% for i in "x"|rjust:"100" %}
...
{% endfor %}
Puede pasar un enlace de
{'n' : range(n) }
a la plantilla, luego haz
{% for i in n %}
...
{% endfor %}
Tenga en cuenta que obtendrá un comportamiento basado en 0 (0, 1, ... n-1).
(Actualizado para compatibilidad con Python3)
range(n)
en python 3, si no recuerdo mal, xrange fue desaprobado
No se pasa a n
sí mismo, sino más bien range(n)
[incluye la lista de enteros de 0 a n-1], desde su punto de vista hasta su plantilla, y en el último lo hace {% for i in therange %}
(si insiste absolutamente en 0 basado en 1 en lugar del 0 normal) basado en índices que puede usar forloop.counter
en el cuerpo del bucle ;-).
En caso de que alguien más se encuentre con esta pregunta ... He creado una etiqueta de plantilla que le permite crear range(...)
: http://www.djangosnippets.org/snippets/1926/
Acepta los mismos argumentos que el 'rango' integrado y crea una lista que contiene El resultado de 'rango'. Sintaxis: {% mkrange [inicio,] parada [, paso] como context_name%} Por ejemplo: {% mkrange 5 10 2 como some_range%} {% para i en some_range%} {{i}}: Algo que quiero repetir \ n {% endfor%} Produce: 5: algo que quiero repetir 7: algo que quiero repetir 9: algo que quiero repetir
Intenté mucho esta pregunta, y encuentro la mejor respuesta aquí: (de cómo recorrer 7 veces en las plantillas de django )
¡Incluso puedes acceder al idx!
views.py:
context['loop_times'] = range(1, 8)
html:
{% for i in loop_times %}
<option value={{ i }}>{{ i }}</option>
{% endfor %}
Puedes pasar :
{'n': rango (n)}
Para usar la plantilla:
{% para i en n%} ... {% endfor%}
Deberías usar " slice " en la plantilla, un ejemplo como este:
en views.py
contexts = {
'ALL_STORES': Store.objects.all(),
}
return render_to_response('store_list.html', contexts, RequestContext(request, processors=[custom_processor]))
en store_list.html:
<ul>
{% for store in ALL_STORES|slice:":10" %}
<li class="store_item">{{ store.name }}</li>
{% endfor %}
</ul>
Este método admite toda la funcionalidad de la range([start,] stop[, step])
función estándar .
<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)
Uso:
{% 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>
Salida
<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))
Solo estoy llevando la respuesta popular un poco más allá y haciéndola más robusta. Esto le permite especificar cualquier punto de inicio, por ejemplo, 0 o 1. También usa la función de rango de Python donde el final es uno menos, por lo que puede usarse directamente con longitudes de lista, por ejemplo.
@register.filter(name='range')
def filter_range(start, end):
return range(start, end)
Luego, en su plantilla, simplemente incluya el archivo de etiqueta de plantilla anterior y use lo siguiente:
{% for c in 1|range:6 %}
{{ c }}
{% endfor %}
Ahora puede hacer 1-6 en lugar de solo 0-6 o codificarlo. Agregar un paso requeriría una etiqueta de plantilla, esto debería cubrir más casos de uso, por lo que es un paso adelante.
Esto esencialmente requiere una range
función. Se generó un ticket de función de Django ( https://code.djangoproject.com/ticket/13088 ) para esto, pero se cerró como "no se solucionará" con el siguiente comentario.
Mi impresión de esta idea es que está tratando de conducir a la programación en la plantilla. Si tiene una lista de opciones que deben representarse, deben calcularse en la vista, no en la plantilla. Si eso es tan simple como un rango de valores, entonces que así sea.
Tienen un buen punto: se supone que las plantillas son representaciones muy simples de la vista. Debe crear los datos requeridos limitados en la vista y pasarlos a la plantilla en el contexto.
Si el número proviene de un modelo, creo que este es un buen parche para el modelo:
def iterableQuantity(self):
return range(self.quantity)
Para aquellos que buscan una respuesta simple, solo necesitan mostrar una cantidad de valores, digamos 3 de 100 publicaciones, por ejemplo, simplemente agreguen {% for post in posts|slice:"3" %}
y repita normalmente y solo se agregarán 3 publicaciones.
{% for i in range(10) %}
{{ i }}
{% endfor %}