Comment écrire une boucle for
numérique dans un modèle Django? Je veux dire quelque chose comme
for i = 1 to n
J'ai utilisé une technique simple qui fonctionne bien pour les petites affaires sans balises spéciales et sans contexte supplémentaire. Parfois, cela est utile
{% for i in '0123456789'|make_list %}
{{ forloop.counter }}
{% endfor %}
Malheureusement, il s’agit de non pris en charge dans le langage de modèle Django. Il y a un couple sur suggestions , mais ils semblent un peu complexes. 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 %}
{% with ''|center:n as range %}
{% for _ in range %}
{{ forloop.counter }}
{% endfor %}
{% endwith %}
Mon point de vue sur cette question, je pense est le plus gentil. Je garde un my_filters.py dans le répertoire des modèles.
@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 %}
Peut-être comme ça?
{% for i in "x"|rjust:"100" %}
...
{% endfor %}
Vous pouvez passer une reliure 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)
Vous ne transmettez pas n
lui-même, 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 faites {% for i in therange %}
(si vous insistez absolument sur un index basé sur 1 plutôt que sur un index normal, vous pouvez utiliser forloop.counter
dans le corps de la boucle ;-).
Si quelqu'un d'autre trouve cette question… J'ai créé une balise de modèle qui vous permet de créer une range(...)
: http://www.djangosnippets.org/snippets/1926/
Accepte les mêmes arguments que la "plage" intégrée et crée une liste contenant Le résultat de "plage". Syntaxe: { % mkrange [start,] stop [ step] as nom_contexte%} Par exemple: {% mkrange 5 10 2 as one_range%} {% for i in some_range%} {{i}}: quelque chose que je veux répéter\n {% end for%} 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 fort sur cette question et je trouve la meilleure réponse ici: (de comment faire une boucle 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 %}
Cette méthode prend en charge toutes les fonctionnalités de la fonction standard 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)
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>
Sortie
<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>
Vous devriez utiliser " slice " dans le template, 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>
Vous pouvez passer:
{'n': range (n)}
Pour utiliser le modèle:
{% pour i dans n%} ... {% endfor%}
Je prends 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, par exemple 0 ou 1. Il utilise également la fonctionnalité range de python où la fin est égale à un de moins, ce qui permet de l'utiliser directement avec les 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 balise 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 0-6 ou le coder en dur. Ajouter une étape nécessiterait une balise de modèle, cela devrait couvrir plus de cas d'utilisation, donc c'est un pas en avant.
Vous pouvez utiliser: {% with ''|center: i as range %}
Cela nécessite essentiellement une fonction range
. Un ticket de fonctionnalité Django a été généré ( https://code.djangoproject.com/ticket/13088 ) mais a été fermé en tant que "ne résoudra pas" avec le commentaire suivant.
Mon impression de cette idée est qu’elle essaie de mener à la programmation dans le modèle. Si vous avez une liste d'options à rendre, elles doivent être calculées dans la vue, pas dans le modèle. Si cela est aussi simple qu'une plage de valeurs, alors qu'il en soit ainsi.
Ils ont un bon point: les modèles sont supposé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 les transmettre au modèle dans le contexte.
Si le numéro provient d'un modèle, j'ai trouvé qu'il s'agissait d'un correctif pour le modèle:
def iterableQuantity(self):
return range(self.quantity)