web-dev-qa-db-fra.com

Numérique pour la boucle dans Django modèles

Comment écrire une boucle for numérique dans un modèle Django? Je veux dire quelque chose comme

for i = 1 to n
232
Lev

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 %}
363
Udi

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 %}
97
tghw
{% with ''|center:n as range %}
{% for _ in range %}
    {{ forloop.counter }}
{% endfor %}
{% endwith %}
94
Tomasz Żyźniewski

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 %}
35
CruelSilence

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)

32
Dave W. Smith

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 ;-).

9
Alex Martelli

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 
 
9
David Wolever

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 %}
6
KKlalala

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>
6
Rebs

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>
6
Vinta

Vous pouvez passer:

{'n': range (n)}

Pour utiliser le modèle:

{% pour i dans n%} ... {% endfor%}

4
rkoots

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.

4
Paul Kenjora

Vous pouvez utiliser: {% with ''|center: i as range %}

4
rkoots

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.

3
Alastair McCormack

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)
0
Alper