Подтвердить что ты не робот

Альтернативная раскраска строк в шаблоне 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 после выхода из рамки

безрезультатно. (Код не работал у меня.)

Я также попытался переместить мой внутренний цикл в пользовательский тег, но это также не сработало, возможно, потому, что цикл компиляции/рендеринга перемещает цикл обратно во внешний цикл? (Независимо от того, почему, это не сработало для меня.)

Как я могу выполнить эту простую задачу!? Я бы предпочел не создавать структуру данных в моем представлении с этой предварительно скомпилированной информацией; что кажется ненужным. Спасибо заранее.

4b9b3361

Ответ 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 %}

Немного более многословный, но не сложно понять, и он отлично работает.

Ответ 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)),
  })