Числовой для цикла в шаблонах Django

188

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

for i = 1 to n
Теги:
django-templates

16 ответов

350

Я использовал простую технику, которая хорошо работает для небольших случаев без специальных тегов и дополнительного контекста. Иногда это пригодится

{% for i in i|rjust:20 %}
    {{ forloop.counter }}
{% endfor %}
  • 2
    Согласовано. Они должны встроить это.
  • 8
    FWIW, 012 == 12, поэтому он будет только зацикливаться на 1 и 2.
Показать ещё 13 комментариев
86

К сожалению, не поддерживается на языке шаблонов Django. Есть пара предложения, но они кажутся немного сложный. Я бы просто поместил переменную в контекст:

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

и в шаблоне:

{% for i in range %}
     ...
{% endfor %}
  • 6
    Мотивы, с помощью которых авторы Django запретили использование простого питона в шаблонах, кажутся бессмысленными и несущественными по сравнению с болью и потерянным временем, связанными с обходом его отсутствия, не говоря уже о необходимости изобретать совершенно новый язык, когда он совершенно потрясающий (питон! ) уже прямо там!
  • 0
    @Bogatyr Если вы этого хотите, просто используйте Jinja2: docs.djangoproject.com/en/1.9/topics/templates/…
83
{% with ''|center:n as range %}
{% for _ in range %}
    {{ forloop.counter }}
{% endfor %}
{% endwith %}
  • 6
    Отличный ответ. Работает, потому что центр создает строку из n пробелов, которые затем зацикливаются. Каждый символ пробела тогда игнорируется, но текущее значение в диапазоне можно найти в forloop.counter (или forloop.counter0). См. Docs.djangoproject.com/en/dev/ref/templates/builtins/#center.
  • 1
    Отличный ответ! Не нужно было создавать новый фильтр.
Показать ещё 2 комментария
69

Мое отношение к этой проблеме, я думаю, самое приятное. Я храню файл my_filters.py в каталоге templatetags.

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

И вы будете использовать вот так:

{% load my_filters %}
{% for i in 15|times %}
    <li>Item</li>
{% endfor %}
  • 0
    Я думаю, что это правильное решение. Выполните range(1, 16) чтобы получить числа, начинающиеся с 1, а не с 0.
  • 0
    Также создайте пустой файл _ init _.py в каталоге templatetags. Также добавьте эти строки в начало my_filters.py from django.template import Library;register = Library()
Показать ещё 2 комментария
34

Может быть, так?

{% for i in "x"|rjust:"100" %}
...
{% endfor %}
29

Вы можете передать привязку

{'n' : range(n) }

в шаблон, затем сделайте

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

Обратите внимание, что вы получите 0-основанное поведение (0, 1,... n-1).

(Обновлено для совместимости с Python3)

  • 1
    Используйте range(n) в Python 3, если я правильно помню, xrange был объявлен устаревшим
  • 0
    Определенно да. И это была одна из двух строк кода, с которой мне пришлось столкнуться при переходе приложения на Python3.
9

Просто, если кто-нибудь еще столкнется с этим вопросом... Я создал тег шаблона, который позволяет вам создать 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

  • 1
    -1 в пользу фрагмента Alex Pi, который добавляет поддержку переменных аргументов.
9

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

6

Я очень старался по этому вопросу, и я нашел лучший ответ здесь: (от как цикл 7 раз в шаблонах django)

Вы даже можете получить доступ к idx!

views.py:

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

HTML:

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

Этот метод поддерживает все функциональные возможности стандартной функции 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>
6

Вы должны использовать " slice" в шаблоне, например:

в 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
    Не уверен, что это то, что искал ОП, но это именно то, что я искал. знак равно
4

Вы можете использовать: {% with ''|center: i as range %}

  • 1
    Можете ли вы привести пример / объяснение того, как это работает?
4

Я просто принимаю популярный ответ немного дальше и делаю его более надежным. Это позволяет указать любую начальную точку, например, 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 или жестко кодировать его. Для добавления шага потребуется шаблонный тег, это должно охватывать больше случаев использования, чтобы сделать шаг вперед.

  • 0
    Это расширение ответа @ guillermo-siliceo-trueba.
2

Это по существу требует функции range. Билет функции Django был поднят (https://code.djangoproject.com/ticket/13088) для этого, но закрыт как "не исправляется" со следующим комментарием.

Мое впечатление от этой идеи заключается в том, что она пытается привести к программированию в шаблоне. Если у вас есть список параметров, которые нужно визуализировать, они должны вычисляться в представлении, а не в шаблоне. Если это так же просто, как диапазон значений, то пусть будет и так.

У них есть хорошая точка. Шаблоны должны быть очень простыми представлениями представления. Вы должны создать ограниченные требуемые данные в представлении и перейти к шаблону в контексте.

  • 3
    Представление должно быть для данных, шаблон должен быть для представления. Представление не должно требовать знания содержимого шаблона, в частности диапазонов. Причина, по которой Джанго игнорирует эти запросы, - полная чушь.
1

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

{'n': range (n)}

Чтобы использовать шаблон:

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

-1

Если число приходит от модели, я нашел, что это хороший патч для модели:

def iterableQuantity(self):
    return range(self.quantity)
  • 2
    Не уверен, почему вы проголосовали, это правильный ответ. Мне не нравится это решение по сравнению с реализацией правильного фильтра, как я предоставил выше. Модели БД должны быть сухими. Но это все же лучше, чем ответ, принятый большинством.
  • 0
    Я даже не знаю ...

Ещё вопросы

Сообщество Overcoder
Наверх
Меню