Альтернативная раскраска строк в шаблоне Django с более чем одним набором строк
Шаблоны Django предлагают встроенный тег cycle
для чередования нескольких значений в разных точках шаблона (или для цикла в шаблоне), но этот тег не reset, когда он доступен в области вне cycle
определение. То есть, если у вас есть два или более списков в вашем шаблоне, строки всех из которых вы хотели бы использовать некоторые определения css odd
и even
, первая строка списка будет забираться там, где последнее прекращено, а не с новой итерацией из вариантов (odd
и even
)
Например, в следующем коде, если первый блог имеет нечетное количество записей, первая запись во втором блоге начнется как even
, когда я хочу, чтобы он начинался с odd
.
{% for blog in blogs %}
{% for entry in blog.entries %}
<div class="{% cycle 'odd' 'even' %}" id="{{entry.id}}">
{{entry.text}}
</div>
{% endfor %}
{% endfor %}
Я попытался устранить это, исправляя тег resetcycle
, предлагаемый здесь:
Билет Django: тег цикла должен reset после выхода из рамки
безрезультатно. (Код не работал у меня.)
Я также попытался переместить мой внутренний цикл в пользовательский тег, но это также не сработало, возможно, потому, что цикл компиляции/рендеринга перемещает цикл обратно во внешний цикл? (Независимо от того, почему, это не сработало для меня.)
Как я могу выполнить эту простую задачу!? Я бы предпочел не создавать структуру данных в моем представлении с этой предварительно скомпилированной информацией; что кажется ненужным. Спасибо заранее.
Ответы
Ответ 1
Самый простой обходной путь (до тех пор, пока патч resetcycle не будет исправлен и не применен) заключается в использовании встроенного фильтра "divisibleby" с forloop.counter:
{% for entry in blog.entries %}
<div class="{% if forloop.counter|divisibleby:2 %}even{% else %}odd{% endif %}" id="{{ entry.id }}">
{{ entry.text }}
</div>
{% endfor %}
Немного более многословный, но не сложно понять, и он отлично работает.
Ответ 2
https://docs.djangoproject.com/en/1.8/ref/templates/builtins/#cycle
{% for o in some_list %}
<tr class="{% cycle 'row1' 'row2' %}">
...
</tr>
{% endfor %}
Ответ 3
Откажитесь и используйте Jinja2 Template System
Я отказался от языка шаблонов django, он очень ограничен в том, что вы можете с ним сделать.
Jinja2 использует тот же синтаксис, который использует шаблон django, но добавляет к нему много улучшений.
EDIT/NOTE (я знаю, это звучит как большой переключатель для незначительной проблемы, но на самом деле я уверен, вы всегда сталкиваетесь с системой шаблонов по умолчанию в django, так что это действительно стоит и я считаю, что это сделает вас более продуктивными в долгосрочной перспективе.)
Вы можете прочитать эту статью, написанную ее автором, хотя она техническая, он упоминает проблему тега {% cycle%} в Джанго.
Jinja не имеет тега цикла, он имеет цикл цикла в цикле:
{% for user in users %}
<li class="{{ loop.cycle('odd', 'even') }}">{{ user }}</li>
{% endfor %}
Основным преимуществом Jinja2 является то, что он позволяет использовать логику для презентации, поэтому, если у вас есть список изображений, вы можете поместить их в таблицу, потому что вы можете запустить новую строку внутри таблицы каждые N элементов, см., вы можете сделать, например:
{% if loop.index is divisibleby(5) %}
</tr>
{% if not loop.last %}
<tr>
{% endif %}
{% endif %}
вы также можете использовать математические выражения:
{% if x > 10 %}
и вы можете напрямую обращаться к своим функциям python (но для настройки функций, которые должны быть выставлены для шаблона, требуется некоторая настройка)
{% for item in normal_python_function_that_returns_a_query_or_a_list() %}
даже заданные переменные..
{% set variable_name = function_that_returns_an_object_or_something() %}
Ответ 4
В итоге я делаю это, с forloop.counter0 - Он отлично работает!
{% for product in products %}
{% if forloop.counter0|divisibleby:4 %}<div class="clear"></div>{% endif %}
<div class="product {% if forloop.counter0|divisibleby:4 %}col{% else %}col20{% endif %}">
Lorem Ipsum is simply dummy text
</div>
{% endfor %}
Ответ 5
Самый простой ответ: "отказаться и использовать jQuery". Если это приемлемо, возможно, это проще, чем сражаться с шаблонами Django над чем-то таким простым.
Ответ 6
Вы можете использовать теги cycle
и resetcycle
(новые в Django 1.11) (от https://docs.djangoproject.com/en/1.11/ref/templates/builtins/#std:templatetag-resetcycle):
{% for blog in blogs %}
{% cycle 'odd' 'even' as rowcolors silent %}
{% resetcycle rowcolors %}
{% for entry in blog.entries %}
{% cycle rowcolors %}
<div class="{{ rowcolors }}" id="{{entry.id}}">
{{ entry.text }}
</div>
{% endfor %}
{% endfor %}
Ответ 7
Есть способ сделать это на стороне сервера с помощью итератора, который не сохраняет одновременную копию всех записей:
import itertools
return render_to_response('template.html',
{
"flattened_entries": itertools.chain(*(blog.entries for blog in blogs)),
})