Réponses:
J'ai utilisé une technique simple qui fonctionne bien pour les petits cas sans balises spéciales et sans contexte supplémentaire. Parfois, cela est utile
{% 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 %}
Malheureusement, cela n'est pas pris en charge dans le langage de modèle Django. Il y a deux ou trois des suggestions , mais ils semblent un peu complexe. Je voudrais juste mettre une variable dans le contexte:
...
render_to_response('foo.html', {..., 'range': range(10), ...}, ...)
...
et dans le modèle:
{% for i in range %}
...
{% endfor %}
Mon point de vue sur cette question, je pense que c'est le plus beau. Je garde un my_filters.py dans le répertoire templatetags.
@register.filter(name='times')
def times(number):
return range(number)
Et vous utiliseriez comme ceci:
{% load my_filters %}
{% for i in 15|times %}
<li>Item</li>
{% endfor %}
range(1, 16)
pour obtenir des nombres à partir de 1, pas de 0.
from django.template import Library;register = Library()
@register.filter(name='range') def filter_range(start, end): return range(start, end)
S'habitue alors comme {% for i in 1|range:6 %}{% endfor %}
. Voir la réponse complète ci-dessous ....
try: return range(number) except: return []
. De cette façon, il ne déclenche jamais d'erreur et renvoie un tableau vide (similaire à la façon dont la plupart des fonctions de modèle fonctionnent).
Peut-être comme ça?
{% for i in "x"|rjust:"100" %}
...
{% endfor %}
Vous pouvez passer une liaison de
{'n' : range(n) }
au modèle, puis faites
{% for i in n %}
...
{% endfor %}
Notez que vous obtiendrez un comportement basé sur 0 (0, 1, ... n-1).
(Mis à jour pour la compatibilité Python3)
range(n)
en python 3, si je me souviens bien, xrange était obsolète
Vous ne vous passez pas n
, mais plutôt range(n)
[la liste des entiers de 0 à n-1 inclus], de votre vue à votre modèle, et dans ce dernier, vous le faites {% for i in therange %}
(si vous insistez absolument sur 1 basé sur le 0 normal index basé sur vous pouvez utiliser forloop.counter
dans le corps de la boucle ;-).
Au cas où quelqu'un d'autre tomberait sur cette question… J'ai créé une balise de modèle qui vous permet de créer un range(...)
: http://www.djangosnippets.org/snippets/1926/
Accepte les mêmes arguments que la fonction intégrée 'range' et crée une liste contenant le résultat de «gamme». Syntaxe: {% mkrange [start,] stop [, step] as context_name%} Par exemple: {% mkrange 5 10 2 as some_range%} {% for i in some_range%} {{i}}: Quelque chose que je veux répéter \ n {% endfor%} Produit: 5: Quelque chose que je veux répéter 7: Quelque chose que je veux répéter 9: Quelque chose que je veux répéter
J'ai essayé très dur sur cette question, et je trouve la meilleure réponse ici: (de la façon de boucler 7 fois dans les modèles django )
Vous pouvez même accéder à l'idx!
views.py:
context['loop_times'] = range(1, 8)
html:
{% for i in loop_times %}
<option value={{ i }}>{{ i }}</option>
{% endfor %}
Tu peux passer :
{'n': plage (n)}
Pour utiliser le modèle:
{% pour i dans n%} ... {% endfor%}
Vous devez utiliser " tranche " dans le modèle, un exemple comme celui-ci:
dans views.py
contexts = {
'ALL_STORES': Store.objects.all(),
}
return render_to_response('store_list.html', contexts, RequestContext(request, processors=[custom_processor]))
dans store_list.html:
<ul>
{% for store in ALL_STORES|slice:":10" %}
<li class="store_item">{{ store.name }}</li>
{% endfor %}
</ul>
Cette méthode prend en charge toutes les fonctionnalités de la range([start,] stop[, step])
fonction standard
<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>
Production
<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"
. Vous devez changer votre code comme suit:args = filter(lambda x: isinstance(x, int) and x >= 0, (_min, _max, _step))
J'amène juste la réponse populaire un peu plus loin et la rend plus robuste. Cela vous permet de spécifier n'importe quel point de départ, donc 0 ou 1 par exemple. Il utilise également la fonction de plage de python où la fin est un de moins afin qu'il puisse être utilisé directement avec des longueurs de liste par exemple.
@register.filter(name='range')
def filter_range(start, end):
return range(start, end)
Ensuite, dans votre modèle, incluez simplement le fichier de balises de modèle ci-dessus et utilisez ce qui suit:
{% for c in 1|range:6 %}
{{ c }}
{% endfor %}
Maintenant, vous pouvez faire 1-6 au lieu de seulement 0-6 ou le coder en dur. L'ajout d'une étape nécessiterait une balise de modèle, cela devrait couvrir plus de cas d'utilisation, c'est donc un pas en avant.
Cela nécessite essentiellement une range
fonction. Un ticket de fonctionnalité Django a été généré ( https://code.djangoproject.com/ticket/13088 ) pour cela, mais fermé comme "ne résoudra pas" avec le commentaire suivant.
Mon impression de cette idée est qu'elle essaie de conduire à la programmation dans le modèle. Si vous avez une liste d'options qui doivent être rendues, elles doivent être calculées dans la vue, pas dans le modèle. Si c'est aussi simple qu'une plage de valeurs, qu'il en soit ainsi.
Ils ont un bon point - les modèles sont censés être des représentations très simples de la vue. Vous devez créer les données requises limitées dans la vue et passer au modèle dans le contexte.
Si le numéro provient d'un modèle, j'ai trouvé que c'était un joli patch pour le modèle:
def iterableQuantity(self):
return range(self.quantity)
Pour ceux qui recherchent une réponse simple, ayant juste besoin d'afficher une quantité de valeurs, disons 3 sur 100 messages par exemple, ajoutez-le {% for post in posts|slice:"3" %}
et bouclez-le normalement et seuls 3 messages seront ajoutés.
{% for i in range(10) %}
{{ i }}
{% endfor %}