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

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

for i = 1 to n

person Lev    schedule 10.07.2009    source источник


Ответы (20)


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

{% for i in '0123456789'|make_list %}
    {{ forloop.counter }}
{% endfor %}
person Udi    schedule 22.04.2011
comment
FWIW, 012 == 12, поэтому будет выполняться цикл только по 1 и 2. - person Bagee; 11.07.2012
comment
{% for i в '0123456789' | make_list%}, чтобы перебрать все 10, не пропуская 0. - person Rick; 18.08.2012
comment
очень умно. как насчет понимания списка? Вид исключает хакерство, но использует ту же идею x = 5, y = [i for i in range (x)] context = {'iterateover': y} - person Dave_750; 26.07.2013
comment
@ Dave_750 context={'iterateover': range(x)} тоже подойдет - person Izkata; 04.09.2013
comment
Это решение не работает, когда длина строки переменная, я имею в виду, когда вы заранее не знаете ее длину. - person Diosney; 22.12.2014
comment
Сгенерируйте строку произвольной длины с помощью 'rjust' {% for i in "x"|rjust:"100" %} - person Aaron; 30.03.2016
comment
Под 4 forcycle не работает. Строка возврата фильтра минимальной длины. - person Petr Pecha; 13.03.2019

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

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

и в шаблоне:

{% for i in range %}
     ...
{% endfor %}
person tghw    schedule 10.07.2009
comment
Мотивация авторов Django к запрету использования простого python в шаблонах кажется бессмысленной и несущественной по сравнению с болью и потерей времени, связанными с работой над его отсутствием, не говоря уже о необходимости изобрести совершенно новый язык, когда это совершенно потрясающий (python! ) уже тут! - person Bogatyr; 11.02.2016
comment
@Bogatyr Если это то, что вы хотите, просто используйте Jinja2: docs.djangoproject.com/en/1.9/topics/templates/ - person tghw; 12.02.2016
comment
@Bogatyr Потому что, очевидно, ничего плохого не происходит, когда вы можете вызвать clear_full_page_cache() в шаблоне (видно в магазине php / magento, на отладку ушло много времени). Наконец, не очень разумно позволять серверу отображать это, когда на стороне клиента это можно сделать так же просто и дешевле, учитывая, что с ним не связаны никакие данные (иначе вы просто повторяете данные). - person Melvyn; 24.03.2021

Я считаю, что мой подход к этому вопросу самый питонический. Создайте 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 %}
person Guillermo Siliceo Trueba    schedule 09.10.2012
comment
Думаю, это правильное решение. Сделайте range(1, 16), чтобы получить числа, начинающиеся с 1, а не с 0. - person chhantyal; 16.02.2015
comment
Также создайте пустой файл _ init _.py в каталоге templatetags. Также добавьте эту строку в начало my_filters.py from django.template import Library;register = Library() - person Ajeeb.K.P; 23.03.2015
comment
Добавьте второй параметр фильтра, и вы получите функцию полного диапазона, встроенную в python. @register.filter(name='range') def filter_range(start, end): return range(start, end) Затем используется как {% for i in 1|range:6 %}{% endfor %}. См. Полный ответ ниже .... - person Paul Kenjora; 05.09.2016
comment
Я немного изменил это (извините, форматирование): try: return range(number) except: return []. Таким образом, он никогда не вызывает ошибку и не возвращает пустой массив (аналогично тому, как работает большинство шаблонных функций). - person Tim Tisdall; 28.09.2017
comment
Мне показалось, что это лучший вариант для решения на питоне. - person artu-hnrq; 07.07.2020

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

{'n' : range(n) }

к шаблону, затем выполните

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

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

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

person Dave W. Smith    schedule 10.07.2009
comment
Используйте range(n) в python 3, если я правильно помню, xrange на нем устарел - person Felício; 11.04.2016
comment
Определенно да. И это была одна из двух строк кода, которые у меня возникли при переводе приложения на Python3. - person Dave W. Smith; 13.04.2016

Может вот так?

{% for i in "x"|rjust:"100" %}
...
{% endfor %}
person CruelSilence    schedule 16.05.2013
comment
Работает, но не легко читается другим разработчиком, который приходит и видит это. - person radtek; 24.03.2021

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

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

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

{% для i в n%} ... {% endfor%}

person rkoots    schedule 25.06.2018
comment
читаемый и простой, легкий для понимания, что происходит, если вы следующий парень, поддерживающий код - person rossdavidh; 03.07.2019

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

person Alex Martelli    schedule 10.07.2009

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

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

views.py:

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

html:

{% for i in loop_times %}
        <option value={{ i }}>{{ i }}</option>
{% endfor %}
person KKlalala    schedule 07.07.2016

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

person David Wolever    schedule 14.02.2010
comment
-1 в пользу сниппета Alex Pi, который добавляет поддержку переменных аргументов. - person m000; 17.08.2012

Этот метод поддерживает все функциональные возможности стандартной функции 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>
person Rebs    schedule 23.02.2016
comment
ваше решение не работает на for value in 0|range:"10,2". Вы должны изменить свой код следующим образом: args = filter(lambda x: isinstance(x, int) and x >= 0, (_min, _max, _step)) - person Bedilbek; 28.02.2020
comment
@Bedilbek: этот код имитирует стандартный диапазон Python. даже он не поддерживает отрицательные диапазоны без явного параметра шага. Список ››› (диапазон (10,2)) [] Список ››› (диапазон (10,2, -1)) [10, 9, 8, 7, 6, 5, 4, 3] - person Rebs; 28.02.2020

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

person Paul Kenjora    schedule 05.09.2016
comment
Это расширение ответа @ guillermo-siliceo-trueba. - person Paul Kenjora; 05.09.2016
comment
Отличный ответ, ты сэкономил мне время - person Shamsul Arefin Sajib; 17.07.2020

Вы должны использовать "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>
person Vinta    schedule 15.08.2012
comment
Не уверен, что это то, что искал OP, но это именно то, что я искал. знак равно - person GChorn; 21.03.2014

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

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

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

person Alastair McCormack    schedule 27.02.2017
comment
Представление должно быть для данных, шаблон - для представления. Представление не должно требовать знания содержимого шаблона, в частности диапазонов. Причина, по которой Django игнорирует эти запросы функций, - полная чушь. - person Rebs; 17.05.2017

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

def iterableQuantity(self):
    return range(self.quantity)
person Alper    schedule 10.03.2011
comment
Не уверен, почему вас не голосуют, это правильный ответ. Мне не нравится это решение по сравнению с реализацией правильного фильтра, как я указал выше. Модели БД должны быть компактными. Но это все же лучше, чем принятый большинством ответ. - person Rebs; 17.05.2017
comment
Я даже не знаю ... - person Alper; 18.05.2017
comment
Я опоздал на 9 лет, но я проголосовал за вас, семья, даже не беспокойтесь об этом. - person Sahil; 08.06.2019

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

person rkoots    schedule 14.09.2016
comment
Можете ли вы привести пример / объяснение того, как это работает? - person Rebs; 17.05.2017

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

person Elias Prado    schedule 14.03.2020

Это показывает от 1 до 20 чисел:

{% for i in "x"|rjust:"20"|make_list %}
 {{ forloop.counter }}
{% endfor %}

также это может вам помочь: (count_all_slider_objects поступают из представлений)

{% for i in "x"|rjust:count_all_slider_objects %}
  {{ forloop.counter }}
{% endfor %}

or

  {% with counter=count_all_slider_objects %}
    {% if list_all_slider_objects %}
      {%  for slide in list_all_slider_objects %}
        {{forloop.counter|add:"-1"}}
        {% endfor%}
      {% endif %}
    {% endwith %}
person namjoo.org    schedule 27.08.2020

person    schedule
comment
Отличный ответ. Работает, потому что center создает строку из n пробелов, которые затем зацикливаются. Затем каждый пробел игнорируется, но текущее значение в диапазоне можно найти в forloop.counter (или forloop.counter0). См. docs.djangoproject.com/en/dev/ref/templates/ builtins / # center - person isedwards; 22.05.2016

person    schedule
comment
Спасибо за ответ. Не могли бы вы отредактировать свой ответ на, включив в него объяснение кода? Это поможет будущим читателям лучше понять, что происходит, и особенно тем членам сообщества, которые плохо знакомы с языком и изо всех сил пытаются понять концепции. - person sta; 05.02.2021
comment
Хотя этот код может предоставить решение вопроса, лучше добавить контекст, объясняющий, почему и как он работает. Это может помочь будущим пользователям изучить и в конечном итоге применить эти знания в своем собственном коде. Вы также, вероятно, получите положительные отзывы / положительные отзывы от пользователей, когда объясните код. - person Amit Verma; 05.02.2021
comment
@AmitVerma ^ Также для вас. - person Jan Kyu Peblik; 11.02.2021

person    schedule
comment
Хотя этот код может ответить на вопрос, предоставление дополнительного контекста относительно того, почему и / или как этот код отвечает на вопрос, улучшает его долгосрочную ценность. - person xiawi; 14.11.2019