Использование значения forloop.counter в качестве индекса списка в шаблоне Django
в моем приложении Django 1.1.1 у меня есть функция в представлении, которая возвращает в свой шаблон диапазон чисел и список списков элементов, например:
...
data=[[item1 , item2, item3], [item4, item5, item6], [item7, item8, item9]]
return render_to_response('page.html', {'data':data, 'cycle':range(0,len(data)-1])
Внутри шаблона у меня есть внешний цикл for, который содержит также еще один цикл для отображения на выходе содержимого внутренних списков данных таким образом
...
{% for page in cycle %}
...
< table >
{% for item in data.forloop.counter0 %}
< tr >< td >{{item.a}} < /td > < td > {{item.b}} ... < /td > < /tr >
...
< /table >
{% endfor %}
{% if not forloop.last %}
< div class="page_break_div" >
{% endif %}
{% endfor %}
...
Но механизм шаблона Django не работает со значением forloop.counter0
как индекс для списка (вместо этого он делает, если я вручную поместил числовое значение в качестве индекса). Есть ли способ, чтобы цикл списка работал с внешним значением forloop.counter0
?
Заранее спасибо за помощь:)
Ответы
Ответ 1
Вы не можете использовать переменные для имен атрибутов, ключей словаря или индексов списка.
Также range(0,len(data)-1]
недействителен python. Это должно быть range(len(data))
.
Вам, вероятно, не нужно cycle
. Может быть, вы хотите это:
{% for itemlist in data %}
...
<table>
{% for item in itemlist %}
< tr >< td >{{item.a}} < /td > < td > {{item.b}} ... < /td > < /tr >
...
{% endfor %}
</table>
{% if not forloop.last %}
<div class="page_break_div">
{% endif %}
{% endfor %}
Ответ 2
Я решил это довольно неэффективно. Если вы читаете этот код, не бросайте его на компьютер. Учитывая два списка одинаковой длины, он будет перебирать первый и печатать соответствующий элемент со второго.
Если вы должны использовать это, используйте его только для редко доступных шаблонов, где длина обоих списков будет мала. В идеале, рефакторинг данных вашего шаблона, чтобы избежать этой проблемы в целом.
{% for list1item in list1 %}
{% for list2item in list2 %}
{% if forloop.counter == forloop.parentloop.counter %}
{{ list1item }} {{ list2item }}
{% endif %}
{% endfor %}
{% endfor %}
Ответ 3
Мне хотелось иметь переменные цвета в моей таблице, используя таблицу стилей, передав список значений True/False. Я нашел это действительно разочаровывающим. В конце я создал список элементов словаря с теми же ключами, что и поля в таблице, плюс еще один с изменением значения true/false.
def jobListView(request):
# django does not allow you to append stuff to the job identity, neither
# will it allow forloop.counter to index another list. The only solution
# is to have the toggle embedded in a dictionary along with
# every field from the job
j = job.objects.order_by('-priority')
# have a toggling true/false list for alternating colours in the table
theTog = True
jobList = []
for i in j:
myJob = {}
myJob['id'] = i.id
myJob['duty'] = i.duty
myJob['updated'] = i.updated
myJob['priority'] = i.priority
myJob['description'] = i.description
myJob['toggle'] = theTog
jobList.append(myJob)
theTog = not(theTog)
# next i
return render_to_response('index.html', locals())
# end jobDetaiView
и мой шаблон
{% if jobList %}
<table border="1"><tr>
<th>Job ID</th><th>Duty</th><th>Updated</th><th>Priority</th><th>Description</th>
</tr>
{% for myJob in jobList %}
<!-- only show jobs that are not closed and have a positive priority. -->
{% if myJob.priority and not myJob.closeDate %}
<!-- alternate colours with the classes defined in the style sheet -->
{% if myJob.toggle %}
<tr class=d1>
{% else %}
<tr class=d0>
{% endif %}
<td><a href="/jobs/{{ myJob.id }}/">{{ myJob.id }}</td><td>{{ myJob.duty }}</td>
<td>{{ myJob.updated }}</td><td>{{ myJob.priority }}</td>
<td class=middle>{{ myJob.description }}</td>
</tr>
{% endif %}
{% endfor %}
</ul>
{% else %}
<p>No jobs are in the system.</p>
{% endif %}