Числові для циклу в шаблонах Джанго


261

Як записати числовий forцикл у шаблон Django? Я маю на увазі щось подібне

for i = 1 to n

Відповіді:


392

Я використовував просту техніку, яка чудово працює для невеликих випадків, без спеціальних тегів і без додаткового контексту. Іноді це стане в нагоді

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

9
FWIW, 012 == 12, тож це буде лише цикл на 1 і 2.
Jason

22
{% for i in '0123456789' | make_list%}, щоб переглядати всі 10, не пропускаючи 0.
Rick

7
Створіть рядок довільної довжини з 'rjust'{% for i in "x"|rjust:"100" %}
Аарон

27
Вже втретє ця відповідь БУДЬ . НЕ використовуйте це. Використовуйте тег шаблону і зробіть це правильно. Я не бачу, як сказати відповідь погано, чи достатньо підстав для видалення коментаря.
Ребс

6
@Rebs Що так поганого в цьому? Звичайно, це хакі, але додавання тегу шаблону лише тому, що вам потрібно один раз перебирати невеликий діапазон у проекті, це теж не чудові рішення.
tobltobs

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

9
Чудова відповідь. Працює тому, що центр створює рядок з n пробілів, які потім перекидаються петлями. Кожен пробіл ігнорується, але поточне значення в діапазоні можна знайти з forloop.counter (або forloop.counter0). Дивіться docs.djangoproject.com/en/dev/ref/templates/builtins/#center
isedwards

2
Чудова відповідь! Не потрібно було створювати новий фільтр.
Мігель Іке

Не потрібно нічого робити з огляду. Відмінний хак
Mohammed Shareef C

106

На жаль, це не підтримується мовою шаблонів Django. Є цілий пар з пропозицій , але вони , здається , трохи складніше. Я просто ставлю змінну в контекст:

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

і в шаблоні:

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

13
Мотивації авторів Джанго за заборону простого пітона в шаблонах здаються безглуздими та безрезультатними в порівнянні з болем і втраченим часом, пов'язаним із тим, щоб не мати його, не кажучи вже про необхідність винайти абсолютно новий мовний ланцюг, коли він ідеально дивовижний (пітон! ) вже тут!
Богатир

2
@Bogatyr Якщо ви цього хочете, просто використовуйте Jinja2: docs.djangoproject.com/en/1.9/topics/templates/…
tghw

78

Я берусь за це питання, я думаю, це найкраще. Я зберігаю my_filters.py у каталозі тегів шаблонів.

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

І ви б використовували так:

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

1
Я думаю, що це правильне рішення. Зробіть, range(1, 16)щоб отримати номери, починаючи з 1, а не 0.
chhantyal

Також створіть порожній файл _ init _.py у каталозі шаблонів тегів. Також додайте цей рядок до початку my_filters.py from django.template import Library;register = Library()
Ajeeb.KP

Додайте другий параметр фільтра, і ви отримаєте функцію повного діапазону, вбудовану в python. @register.filter(name='range') def filter_range(start, end): return range(start, end)Потім звикає як {% for i in 1|range:6 %}{% endfor %}. Дивіться повну відповідь нижче ....
Пол Кеньора

Я дещо змінив це (виправдання форматування): try: return range(number) except: return [] . Таким чином, він ніколи не викликає помилку і повертає порожній масив (подібно до того, як працюють більшість функцій шаблону).
Тім Тісдалл


41

Ви можете пройти обв'язку

{'n' : range(n) }

до шаблону, потім зробіть

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

Зауважте, що ви отримаєте поведінку на основі 0 (0, 1, ... n-1).

(Оновлено для сумісності Python3)


1
Використовуйте range(n)в python 3, якщо я його правильно пам’ятаю, xrange був застарілий на ньому
Felício

Дійсно так. І це був один з двох рядків коду, який мені довелося випадково перейти на додаток до Python3.
Дейв В. Сміт

9

Ви не передаєте nсебе, а скоріше range(n)[список цілих чисел від 0 до n-1 включено], з вашого погляду на ваш шаблон, і в останньому ви це зробите {% for i in therange %}(якщо ви абсолютно наполягаєте на 1-основі, а не на звичайному 0 -оснований індекс, який можна використовувати forloop.counterв тілі циклу ;-).


9

Тільки у випадку, коли хтось інший стикається з цим питанням ... Я створив тег шаблонів, який дозволяє створити range(...): http://www.djangosnippets.org/snippets/1926/

Приймає ті ж аргументи, що і вбудований 'діапазон' та створює список, що містить
результат 'діапазону'.

Синтаксис:
    {% mkrange [початок,] зупинка [, крок] як контекст_імен%}

Наприклад:
    {% mkrange 5 10 2 як some_range%}
    {% для i в some_range%}
      {{i}}: Щось я хочу повторити \ n
    {% endfor%}

Виробляє:
    5: Щось я хочу повторити 
    7: Щось я хочу повторити 
    9: Щось я хочу повторити


1
-1 на користь фрагмента Алекса Пі, який додає підтримку змінних аргументів.
m000


9

Ви можете пройти:

{'n': діапазон (n)}

Щоб використовувати шаблон:

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


читабельний і простий, легко зрозуміти, що відбувається, якщо ви наступний хлопець, який підтримує код
rossdavidh

7

Ви повинні використовувати " скибочку " у шаблоні, наприклад такий:

у views.py

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

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

в store_list.html:

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

1
Не впевнений, чи це саме те, що шукала ОП, але саме це я шукав. =)
GChorn

7

Цей метод підтримує всю функціональність стандартної 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)

Використання:

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

Вихідні дані

<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". Ви повинні змінити свій код так:args = filter(lambda x: isinstance(x, int) and x >= 0, (_min, _max, _step))
Bedilbek

@Bedilbek цей код імітує стандартний діапазон пітона. навіть він не підтримує негативні діапазони без явного параметра кроку. >>> список (діапазон (10,2)) [] >>> список (діапазон (10,2, -1)) [10, 9, 8, 7, 6, 5, 4, 3]
Rebs

5

Я просто забираю популярну відповідь трохи далі і роблю її більш надійною. Це дозволяє вказати будь-яку початкову точку, наприклад 0 або 1, наприклад. Він також використовує функцію діапазону python, де кінець менше одного, тому його можна використовувати, наприклад, із довжиною списку, наприклад.

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

Потім у свій шаблон просто включіть вищевказаний файл тегу шаблону та скористайтеся наступним:

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

Тепер ви можете зробити 1-6, а не лише 0-6 або жорстке їх кодування. Якщо додати крок, знадобиться тег шаблону, він повинен охоплювати більше випадків використання, тому це крок вперед.


Це розширення відповіді @ guillermo-siliceo-trueba.
Пол Кеньора

5

Це по суті вимагає rangeфункції. Квиток на функцію "Джанго" було піднято ( https://code.djangoproject.com/ticket/13088 ) для цього, але закрито, оскільки "не виправиться" із наступним коментарем.

Моє враження від цієї ідеї полягає в тому, що вона намагається привести до програмування в шаблоні. Якщо у вас є перелік параметрів, які потрібно візуалізувати, їх слід обчислити у поданні, а не в шаблоні. Якщо це так просто, як діапазон значень, то так і буде.

Вони мають гарний момент - шаблони повинні бути дуже простими уявленнями про погляд. Вам слід створити обмежені необхідні дані у поданні та передати шаблону в контексті.


6
Перегляд має бути для даних, шаблон повинен бути представлений. Перегляд не повинен вимагати знання змісту шаблону, зокрема діапазону. Причиною Джанго ігнорування цих запитів на функцію є сміття.
Ребс

3

Ви можете використовувати: {% with ''|center: i as range %}


1
Чи можете ви навести приклад / пояснення, як це працює?
Ребс

1

Для тих, хто шукає простої відповіді, просто потрібно відобразити кількість значень, скажімо, 3 зі 100 повідомлень, наприклад, просто додайте {% for post in posts|slice:"3" %}і циклічно додайте її, і лише 3 повідомлення будуть додані.


0

Якщо номер походить від моделі, я вважаю, що це хороший виправлення до моделі:

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

2
Не впевнений, чому ви проголосували, це правдива відповідь. Мені це рішення не подобається порівняно із застосуванням відповідного фільтра, як я запропонував вище. Моделі БД повинні зберігатися худорлявими. Але це все-таки краще, ніж більшість прийнятих відповідей.
Ребс

Я навіть не знаю…
Альпер

Я на 9 років занадто пізно, але я підтримав вас фами, навіть не турбуйтеся про це.
Сахил

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

{% endfor %}

Хоча цей код може відповісти на питання, надаючи додатковий контекст щодо того, чому та / або як цей код відповідає на питання, покращує його довгострокове значення.
xiawi
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.