Numerisch für Schleife in Django-Vorlagen


261

Wie schreibe ich eine numerische forSchleife in eine Django-Vorlage? Ich meine so etwas wie

for i = 1 to n

Antworten:


392

Ich habe eine einfache Technik verwendet, die für kleine Fälle ohne spezielle Tags und ohne zusätzlichen Kontext gut funktioniert. Manchmal ist das praktisch

{% for i in '0123456789'|make_list %}
    {{ forloop.counter }}
{% endfor %}

9
FWIW, 012 == 12, so wird es nur über 1 und 2
schleifen

22
{% für i in '0123456789' | make_list%}, um über alle 10 zu iterieren, ohne 0 zu überspringen.
Rick

7
Generieren Sie eine Zeichenfolge beliebiger Länge mit 'rjust'{% for i in "x"|rjust:"100" %}
Aaron

27
Zum dritten Mal ist diese Antwort schlecht . Verwenden Sie dies NICHT. Verwenden Sie ein Vorlagen-Tag und machen Sie es richtig. Ich verstehe nicht, wie schlecht es ist, eine Antwort zu sagen, Grund genug, einen Kommentar zu löschen.
Rebs

6
@Rebs Was ist das so schlimm daran? Sicher, es ist hackig, aber das Hinzufügen eines Vorlagen-Tags, nur weil Sie einmal in einem Projekt einen kleinen Bereich durchlaufen müssen, ist auch keine so gute Lösung.
tobltobs

113
{% with ''|center:n as range %}
{% for _ in range %}
    {{ forloop.counter }}
{% endfor %}
{% endwith %}

9
Gute Antwort. Funktioniert, weil center eine Zeichenfolge von n Leerzeichen erstellt, die dann durchlaufen werden. Jedes Leerzeichen wird dann ignoriert, aber der aktuelle Wert im Bereich kann aus forloop.counter (oder forloop.counter0) abgerufen werden. Siehe docs.djangoproject.com/de/dev/ref/templates/builtins/#center
isedwards

2
Gute Antwort! Musste keinen neuen Filter erstellen.
Miguel Ike

Sie müssen nichts im Blick haben. Ausgezeichneter Hack
Mohammed Shareef C

106

Leider wird dies in der Django-Vorlagensprache nicht unterstützt . Es gibt ein paar von Anregungen , aber sie scheinen ein wenig komplexer. Ich würde nur eine Variable in den Kontext setzen:

...
render_to_response('foo.html', {..., 'range': range(10), ...}, ...)
...

und in der Vorlage:

{% for i in range %}
     ...
{% endfor %}

13
Die Motive, die die Django-Autoren hatten, einfaches Python in Vorlagen nicht zuzulassen, scheinen sinnlos und belanglos zu sein, verglichen mit dem Schmerz und der verlorenen Zeit, die damit verbunden sind, es nicht zu haben, ganz zu schweigen von der Notwendigkeit, eine völlig neue Sprache zu erfinden, wenn eine vollkommen großartige (Python! ) ist schon richtig da!
Bogatyr

2
@ Bogatyr Wenn Sie das möchten, verwenden Sie einfach Jinja2: docs.djangoproject.com/de/1.9/topics/templates/…
tghw

78

Meine Meinung zu diesem Thema finde ich am schönsten. Ich behalte eine my_filters.py im Templatetags-Verzeichnis.

@register.filter(name='times') 
def times(number):
    return range(number)

Und Sie würden so verwenden:

{% load my_filters %}
{% for i in 15|times %}
    <li>Item</li>
{% endfor %}

1
Ich denke, das ist die richtige Lösung. Sind die range(1, 16)Zahlen von 1 beginnen zu bekommen, nicht 0.
chhantyal

Erstellen Sie auch eine leere Datei _ init _.py im Verzeichnis templatetags. Fügen Sie diese Zeile auch oben in my_filters.py from django.template import Library;register = Library()
Ajeeb.KP

Wenn Sie einen zweiten Filterparameter hinzufügen, erhalten Sie die in Python integrierte Vollbereichsfunktion. @register.filter(name='range') def filter_range(start, end): return range(start, end)Dann wird als verwendet {% for i in 1|range:6 %}{% endfor %}. Siehe die vollständige Antwort unten ....
Paul Kenjora

Ich habe dies leicht geändert (Entschuldigung Formatierung) : try: return range(number) except: return []. Auf diese Weise wird niemals ein Fehler ausgelöst und ein leeres Array zurückgegeben (ähnlich wie bei den meisten Vorlagenfunktionen).
Tim Tisdall


41

Sie können eine Bindung von übergeben

{'n' : range(n) }

zur Vorlage, dann tun

{% for i in n %}
...
{% endfor %}

Beachten Sie, dass Sie ein 0-basiertes Verhalten erhalten (0, 1, ... n-1).

(Aus Gründen der Python3-Kompatibilität aktualisiert)


1
Verwenden Sie range(n)in Python 3, wenn ich mich richtig erinnere, war xrange darauf veraltet
Felício

In der Tat, ja. Und das war eine von zwei Codezeilen, die ich beim Übergang einer App zu Python3 zufällig hatte.
Dave W. Smith

9

Sie übergeben sich nicht nselbst, sondern range(n)[die Liste der Ganzzahlen von 0 bis n-1 eingeschlossen] aus Ihrer Sicht in Ihre Vorlage, und in letzterer tun Sie dies {% for i in therange %}(wenn Sie absolut auf 1-basierten statt auf der normalen 0 bestehen -basierter Index, den Sie forloop.counterim Körper der Schleife verwenden können ;-).


9

Nur für den Fall, dass jemand anderes auf diese Frage stößt ... Ich habe ein Vorlagen-Tag erstellt, mit dem Sie Folgendes erstellen können range(...): http://www.djangosnippets.org/snippets/1926/

Akzeptiert dieselben Argumente wie der integrierte Bereich und erstellt eine Liste mit
das Ergebnis von 'Reichweite'.

Syntax:
    {% mkrange [start,] stop [, step] als Kontextname%}

Beispielsweise:
    {% mkrange 5 10 2 als some_range%}
    {% für i in some_range%}
      {{i}}: Etwas, das ich wiederholen möchte \ n
    {% endfor%}

Produziert:
    5: Etwas, das ich wiederholen möchte 
    7: Etwas, das ich wiederholen möchte 
    9: Etwas, das ich wiederholen möchte


1
-1 zugunsten von Alex Pis Snippet, das die Unterstützung variabler Argumente hinzufügt.
M000

9

Ich habe mich sehr um diese Frage bemüht und finde hier die beste Antwort: (von wie man 7-mal in den Django-Vorlagen schleift )

Sie können sogar auf die IDX zugreifen!

views.py:

context['loop_times'] = range(1, 8)

html:

{% for i in loop_times %}
        <option value={{ i }}>{{ i }}</option>
{% endfor %}

9

Du kannst passieren :

{'n': Bereich (n)}

So verwenden Sie die Vorlage:

{% für i in n%} ... {% endfor%}


lesbar und einfach, leicht zu verstehen, was passiert, wenn Sie der nächste sind, der den Code verwaltet
Rossdavidh

7

Sie sollten " Slice " in der Vorlage verwenden, ein Beispiel wie das folgende:

in views.py

contexts = {
    'ALL_STORES': Store.objects.all(),
}

return render_to_response('store_list.html', contexts, RequestContext(request, processors=[custom_processor]))

in store_list.html:

<ul>
{% for store in ALL_STORES|slice:":10" %}
    <li class="store_item">{{ store.name }}</li>
{% endfor %}
</ul>

1
Ich bin mir nicht sicher, ob das OP gesucht hat, aber genau das habe ich gesucht. =)
GChorn

7

Dieses Verfahren unterstützt alle Funktionen der range([start,] stop[, step])Standardfunktion

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

Verwendungszweck:

{% 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>

Ausgabe

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

Ihre Lösung funktioniert nicht for value in 0|range:"10,2". Sie müssen Ihren Code wie folgt ändern:args = filter(lambda x: isinstance(x, int) and x >= 0, (_min, _max, _step))
Bedilbek

@Bedilbek Dieser Code ahmt den Standard-Python-Bereich nach. Selbst negative Bereiche ohne expliziten Schrittparameter werden nicht unterstützt. >>> Liste (Bereich (10,2)) [] >>> Liste (Bereich (10,2, -1)) [10, 9, 8, 7, 6, 5, 4, 3]
Rebs

5

Ich gehe die beliebte Antwort nur ein bisschen weiter und mache sie robuster. Auf diese Weise können Sie einen beliebigen Startpunkt angeben, z. B. 0 oder 1. Es verwendet auch die Python-Bereichsfunktion, bei der das Ende eins weniger ist, sodass es beispielsweise direkt mit Listenlängen verwendet werden kann.

@register.filter(name='range')
def filter_range(start, end):
  return range(start, end)

Fügen Sie dann in Ihre Vorlage einfach die obige Vorlagen-Tag-Datei ein und verwenden Sie Folgendes:

{% for c in 1|range:6 %}
{{ c }}
{% endfor %}

Jetzt können Sie 1-6 statt nur 0-6 oder hartes Codieren ausführen. Das Hinzufügen eines Schritts würde ein Vorlagen-Tag erfordern. Dies sollte mehr Anwendungsfälle abdecken, sodass es ein Fortschritt ist.


Dies ist eine Erweiterung der @ guillermo-siliceo-trueba-Antwort.
Paul Kenjora

5

Dies erfordert im Wesentlichen eine rangeFunktion. Hierfür wurde ein Django-Feature-Ticket ( https://code.djangoproject.com/ticket/13088 ) erstellt, das jedoch mit dem folgenden Kommentar als "nicht behoben" geschlossen wurde.

Mein Eindruck von dieser Idee ist, dass sie versucht, zur Programmierung in der Vorlage zu führen. Wenn Sie eine Liste von Optionen haben, die gerendert werden müssen, sollten diese in der Ansicht und nicht in der Vorlage berechnet werden. Wenn das so einfach ist wie ein Wertebereich, dann soll es so sein.

Sie haben einen guten Punkt - Vorlagen sollen sehr einfache Darstellungen der Ansicht sein. Sie sollten die begrenzten erforderlichen Daten in der Ansicht erstellen und im Kontext an die Vorlage übergeben.


6
Die Ansicht sollte für Daten sein, die Vorlage sollte für die Präsentation sein. Die Ansicht sollte keine Kenntnis des Inhalts der Vorlage erfordern, insbesondere der Bereiche. Djangos Grund, diese Feature-Anfragen zu ignorieren, ist völliger Quatsch.
Rebs

3

Sie können verwenden: {% with ''|center: i as range %}


1
Können Sie ein Beispiel / eine Erklärung geben, wie dies funktioniert?
Rebs

1

Für diejenigen, die nach einer einfachen Antwort suchen und nur eine Anzahl von Werten anzeigen müssen, sagen wir 3 von 100 Posts, zum Beispiel fügen Sie {% for post in posts|slice:"3" %}sie einfach hinzu und wiederholen Sie sie normal, und es werden nur 3 Posts hinzugefügt.


0

Wenn die Nummer von einem Modell stammt, fand ich, dass dies ein schöner Patch für das Modell ist:

def iterableQuantity(self):
    return range(self.quantity)

2
Ich bin mir nicht sicher, warum Sie nicht gewählt werden, es ist eine gültige Antwort. Ich mag diese Lösung nicht im Vergleich zur Implementierung eines geeigneten Filters, wie ich oben angegeben habe. DB-Modelle sollten schlank gehalten werden. Aber es ist immer noch besser als die von der Mehrheit akzeptierte Antwort.
Rebs

Ich weiß nicht einmal ...
Alper

Ich bin 9 Jahre zu spät, aber ich habe dich gestimmt, fam, mach dir keine Sorgen.
Sahil

-5
{% for i in range(10) %}
   {{ i }}

{% endfor %}

Während dieser Code die Frage möglicherweise beantwortet, verbessert die Bereitstellung eines zusätzlichen Kontexts darüber, warum und / oder wie dieser Code die Frage beantwortet, ihren langfristigen Wert.
Xiawi
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.