Numérique pour boucle dans les modèles Django
Comment écrire une boucle numérique for
dans un modèle Django? Je veux dire quelque chose comme
for i = 1 to n
16 réponses
j'ai utilisé une technique simple qui fonctionne bien pour les petits cas sans étiquettes spéciales et sans contexte supplémentaire.
{% for i in "xxxxxxxxxxxxxxxxxxxx" %}
{{ forloop.counter0 }}
{% endfor %}
ajustez la longueur de "xxxxxxxxxxxxxxxxxxxx" selon vos besoins. "xxx" pour faire 3 itérations, etc.
malheureusement, c'est non pris en charge dans le langage de Django template. Il y a un couple de 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 sur le templatetags répertoire.
@register.filter(name='times')
def times(number):
return range(number)
et vous utilisez 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 faire
{% 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 passez pas n
lui-même, mais plutôt range(n)
[la liste des entiers de 0 à n-1 inclus], de votre point de vue à votre modèle, et dans ce dernier vous faites {% for i in therange %}
(si vous insistez absolument sur 1-basé plutôt que le Normal 0-basé l'index, vous pouvez utiliser forloop.counter
dans le corps de la boucle; -).
juste au cas où quelqu'un d'autre tombe sur cette question... j'ai créé un template tag qui vous permet de créer un 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
Vous devez utiliser " tranche " dans le modèle, un exemple comme ceci:
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 norme range([start,] stop[, step])
fonction
<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)
Utilisation:
{% 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>
j'ai essayé très fort sur cette question, et je trouve la meilleure réponse ici: (à partir 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 %}
je vais juste pousser un peu plus loin la réponse populaire et la rendre 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 fonctionnalité de portée de python où la fin est une de moins, de sorte qu'il peut être utilisé 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, il suffit d'inclure le fichier tag template ci-dessus et d'utiliser ce qui suit:
{% for c in 1|range:6 %}
{{ c }}
{% endfor %}
Maintenant, vous pouvez faire 1-6 au lieu de seulement 0-6 ou codage dur il. Ajouter une étape nécessiterait une étiquette de modèle, cela devrait couvrir plus de cas d'utilisation donc c'est un pas en avant.
cela nécessite essentiellement une fonction range
. Un billet spécial Django a été augmenté ( https://code.djangoproject.com/ticket/13088 ) pour cela, mais fermé comme" ne sera pas fixer " avec le commentaire suivant.
mon impression de cette idée est qu'il essaie de conduire à la programmation dans le modèle. Si vous avez une liste d'options qui doivent être rendus, ils doivent être calculées de la vue, et non pas dans le modèle. Si c'est comme simple comme une plage de valeurs, alors ainsi soit-il.
ils ont un bon point - les gabarits 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.
vous pouvez passer:
{'n': range (n) }
pour utiliser le modèle:
{%pour i en n %} ... {% finpour %}
si le numéro vient d'un modèle, j'ai trouvé que c'est un bon patch pour le modèle:
def iterableQuantity(self):
return range(self.quantity)