Reputation: 3856
When iterating through a list in one of my Django templates, I'm trying to put in some if logic to say 'if the last items 'type' value is equal to the current item in the loops 'type' value, but it seems that python syntax for doing that is not allowed in a Django template. I know I can use {{ forloop.counter }}, but I can't seem to use that counter to get an item from my list at a specific index.
HTML
{% for repair in repairs %}
{% if repairs[{{ forloop.counter - 1}}].type == repair.type %}<div class="col-sm-12" style="border-top: 1px solid grey; border-bottom: 1px solid grey;"><h2>{{ repair.type }}</h2></div>{% endif %}
<div class="col-sm-6">
<label>
<input type="checkbox" name="{{ repair }}">
{{ repair }}</label>
</div>
{% endfor %}
or also
{% for index, repair in enumerate(repairs) %}
{% if repairs[index - 1].type == repair.type%}<div class="col-sm-12" style="border-top: 1px solid grey; border-bottom: 1px solid grey;"><h2>{{ repair.type }}</h2></div>{% endif %}
<div class="col-sm-6">
<label>
<input type="checkbox" name="{{ repair }}">
{{ repair }}</label>
</div>
{% endfor %}
Upvotes: 0
Views: 1809
Reputation: 32274
There is a built-in template tag for your use-case regroup
{% regroup repairs by type as types %}
{% for type in types %}
<div class="col-sm-12" style="border-top: 1px solid grey; border-bottom: 1px solid grey;"><h2>{{ type.grouper}}</h2></div>
{% for repair in type.list %}
<div class="col-sm-6">
<label>
<input type="checkbox" name="{{ repair }}">{{ repair }}
</label>
</div>
{% endfor %}
{% endfor %}
Upvotes: 0
Reputation: 738
There are multiple issues with your code.
As noted by Justin, Django templates do not allow you to access a list element using something like list[index]
. Instead you should do list.index
Django template Engine have no way to determine the type of a variable. You can, though, implement a template filter and use it to determine the type of a variable as explained in this answer.
Also, instead of {{ forloop.counter - 1}}
, you should do {{ forloop.counter0 - 1}}
. forloop.counter
gives a 1-indexed iteration of the loop whereas forloop.counter0
gives a 0-indexed iteration of the loop.
So your final code should look something like:
from django import template
register = template.Library()
@register.filter
def get_type(value):
return type(value)
{% for repair in repairs %}
{% if repairs.{{ forloop.counter0 - 1}}|get_type == repair|get_type %}
<div class="col-sm-12" style="border-top: 1px solid grey; border-bottom: 1px solid grey;">
<h2>{{ repair|get_type }}</h2>
</div>
{% endif %}
<div class="col-sm-6">
<label>
<input type="checkbox" name="{{ repair }}">
{{ repair }}
</label>
</div>
{% endfor %}
Edit: After you clarified, that 'type' is actually an attribute of the variable, here is what your code should be:
{% for repair in repairs %}
{% if repairs.{{ forloop.counter0 - 1}}.type == repair.type %}
<div class="col-sm-12" style="border-top: 1px solid grey; border-bottom: 1px solid grey;">
<h2>{{ repair.type }}</h2>
</div>
{% endif %}
<div class="col-sm-6">
<label>
<input type="checkbox" name="{{ repair }}">
{{ repair }}
</label>
</div>
{% endfor %}
Of course, the method suggested by Daniel is a better way to do this.
Upvotes: 0
Reputation: 599778
You should be able to use ifchanged
for this.
{% for repair in repairs %}
{% ifchanged repair.type %}<div class="col-sm-12" style="border-top: 1px solid grey; border-bottom: 1px solid grey;"><h2>{{ repair.type }}</h2></div>{% endifchanged %}
...
{% endfor %}
Upvotes: 1