Odpowiedzi:
Użyłem prostej techniki, która działa dobrze w małych skrzyniach bez specjalnych znaczników i bez dodatkowego kontekstu. Czasami jest to przydatne
{% 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 %}
Niestety nie jest to obsługiwane w języku szablonów Django. Istnieje kilka z propozycji , ale wydaje się trochę skomplikowane. Po prostu umieściłbym zmienną w kontekście:
...
render_to_response('foo.html', {..., 'range': range(10), ...}, ...)
...
i w szablonie:
{% for i in range %}
...
{% endfor %}
Uważam, że jest to najlepsze. Trzymam my_filters.py w katalogu templatetags.
@register.filter(name='times')
def times(number):
return range(number)
I użyłbyś takiego:
{% load my_filters %}
{% for i in 15|times %}
<li>Item</li>
{% endfor %}
range(1, 16)
uzyskać liczby zaczynające się od 1, a nie od 0
from django.template import Library;register = Library()
@register.filter(name='range') def filter_range(start, end): return range(start, end)
Następnie przyzwyczaja się jako {% for i in 1|range:6 %}{% endfor %}
. Zobacz pełną odpowiedź poniżej ...
try: return range(number) except: return []
. W ten sposób nigdy nie zgłasza błędu i zwraca pustą tablicę (podobnie jak działa większość funkcji szablonu).
Może tak?
{% for i in "x"|rjust:"100" %}
...
{% endfor %}
Możesz przekazać powiązanie
{'n' : range(n) }
do szablonu, a następnie zrób
{% for i in n %}
...
{% endfor %}
Zauważ, że otrzymasz zachowanie oparte na 0 (0, 1, ... n-1).
(Zaktualizowano dla kompatybilności z Python3)
range(n)
w pythonie 3, jeśli dobrze pamiętam, xrange był na nim przestarzały
Nie przekazujesz n
się, ale raczej range(n)
[dołączona lista liczb całkowitych od 0 do n-1], z twojego widoku do szablonu, a w tym drugim robisz {% for i in therange %}
(jeśli absolutnie nalegasz na 1 zamiast zwykłego 0 oparty na indeksie, którego można użyć forloop.counter
w ciele pętli ;-).
Wystarczy, że ktokolwiek napotka to pytanie… Stworzyłem tag szablonu, który pozwala ci stworzyć range(...)
: http://www.djangosnippets.org/snippets/1926/
Akceptuje te same argumenty, co wbudowane „zakres” i tworzy listę zawierającą wynik „zasięgu”. Składnia: {% mkrange [start,] stop [, krok] jako nazwa_kontekstu%} Na przykład: {% mkrange 5 10 2 as some_range%} {% for i in some_range%} {{i}}: Coś, co chcę powtórzyć \ n {% endfor%} Produkuje: 5: Coś, co chcę powtórzyć 7: Coś, co chcę powtórzyć 9: Coś, co chcę powtórzyć
Bardzo się starałem na to pytanie i znajduję najlepszą odpowiedź tutaj: (od tego, jak zapętlić 7 razy w szablonach django )
Możesz nawet uzyskać dostęp do idx!
views.py:
context['loop_times'] = range(1, 8)
HTML:
{% for i in loop_times %}
<option value={{ i }}>{{ i }}</option>
{% endfor %}
Możesz przekazać:
{'n': zakres (n)}
Aby użyć szablonu:
{% for i in n%} ... {% endfor%}
W szablonie należy użyć „ plasterka ”, na przykład:
w views.py
contexts = {
'ALL_STORES': Store.objects.all(),
}
return render_to_response('store_list.html', contexts, RequestContext(request, processors=[custom_processor]))
w store_list.html:
<ul>
{% for store in ALL_STORES|slice:":10" %}
<li class="store_item">{{ store.name }}</li>
{% endfor %}
</ul>
Metoda ta obsługuje wszystkie funkcje standardowej range([start,] stop[, step])
funkcji
<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)
Stosowanie:
{% 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>
Wynik
<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"
. Musisz zmienić kod w następujący sposób:args = filter(lambda x: isinstance(x, int) and x >= 0, (_min, _max, _step))
Po prostu posuwam popularną odpowiedź nieco dalej i robię ją bardziej niezawodną. Umożliwia to określenie dowolnego punktu początkowego, na przykład 0 lub 1. Używa także funkcji zakresu Pythona, gdzie koniec jest o jeden mniejszy, więc można go użyć bezpośrednio na przykład z długością listy.
@register.filter(name='range')
def filter_range(start, end):
return range(start, end)
Następnie w swoim szablonie po prostu dołącz powyższy plik znacznika szablonu i użyj następujących poleceń:
{% for c in 1|range:6 %}
{{ c }}
{% endfor %}
Teraz możesz zrobić 1-6 zamiast tylko 0-6 lub kodować na stałe. Dodanie kroku wymagałoby tagu szablonu, który powinien obejmować więcej przypadków użycia, więc jest to krok naprzód.
Zasadniczo wymaga to range
funkcji. Zgłoszono bilet funkcji Django ( https://code.djangoproject.com/ticket/13088 ), ale zamknięto go jako „nie można naprawić” następującym komentarzem.
Mam wrażenie, że ten pomysł jest taki, że próbuje doprowadzić do programowania w szablonie. Jeśli masz listę opcji, które należy wyrenderować, należy je obliczyć w widoku, a nie w szablonie. Jeśli to tak proste jak zakres wartości, niech tak będzie.
Mają dobrą rację - szablony mają być bardzo prostymi reprezentacjami widoku. Należy utworzyć ograniczone wymagane dane w widoku i przekazać szablon w kontekście.
Dla tych, którzy szukają prostej odpowiedzi, tylko wyświetlającej liczbę wartości, powiedzmy, że na przykład 3 ze 100 postów po prostu dodają {% for post in posts|slice:"3" %}
i zapętlają ją normalnie, a zostaną dodane tylko 3 posty.
Jeśli numer pochodzi z modelu, uważam, że jest to przyjemna łatka do modelu:
def iterableQuantity(self):
return range(self.quantity)
{% for i in range(10) %}
{{ i }}
{% endfor %}