Django templates: forloop.first and forloop.last
Question:
I have the following code in my template:
{% for f in friendslist %}
{% if forloop.first %}
// display something
{% endif %}
// display stuff
{% if forloop.last %}
// display something
{% endif %}
{% endfor %}
It works as expected when there is more than one item in the friendslist. But if there is just 1 item, then the content inside the forloop.last
conditional does not display.
I guess this is because the loop in that case is the first, but I mean it’s also the last right? So why dosn’t both contents inside first and last
conditional show?
Answers:
In my code they both execute if there is only one element in friendslist. Here is a test you can run in the shell where maybe you can figure out what isn’t working:
$ ./manage.py shell
>>> from django import template
>>> t = template.Template("""{% for f in friendslist %}
{% if forloop.first %}
First of the loop
{% endif %}
{{ f }}
{% if forloop.last %}
Last of the loop
{% endif %}
{% endfor %}""")
>>> c = template.Context({'friendslist' : ['one element',]})
>>> t.render(c)
First of the loop
one element
Last of the loop
couldn’t you just use an “or” tag like {% if forloop.last or friendlist.count == 1 %}
{% for f in friendslist %}
{% if forloop.first %}
// display something
{% endif %}
// display stuff
{% if forloop.last or friendlist.count == 1 %}
// display something
{% endif %}
{% endfor %}
You can also use ”not” in template to solve this. It works even there is just an item in the list.
{% for friend in friendslist %}
{% if not forloop.last %}
// display something
{% endif %}
{% if forloop.last %}
// display something
{% endif %}
{% endfor %}
Exemplifying the accepted answer for when you need to access a nested json that contains arrays of jsons, and get only the first element.
In the example below, in regards to users’ addresses, I want to show only the phone number of the first phone registered in the user profile.
Example users
json that will be passed to the HTML template
{
"name": "user1",
"birthdate": "date1",
"phones": [
{
"number": "111111111",
"type": "type1"
},
{
"number": "222222222",
"type": "type2"
}
],
}
HTML file to render this example in a table, using Jinja:
<table id="users_table" class="table table-hover table-sm">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Username</th>
<th scope="col">Birthdate</th>
<th scope="col">Phone</th>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr>
<th scope="row">{{ forloop.counter }}</th>
<td>{{ user.name }}</td>
<td>{{ user.birthdate }}</td>
{% for phone in user.phones %}
{% if forloop.first %}
<td> {{ phone.number }}</td>
{% endif %}
{% endfor %}
</tr>
</tbody>
</table>
I have the following code in my template:
{% for f in friendslist %}
{% if forloop.first %}
// display something
{% endif %}
// display stuff
{% if forloop.last %}
// display something
{% endif %}
{% endfor %}
It works as expected when there is more than one item in the friendslist. But if there is just 1 item, then the content inside the forloop.last
conditional does not display.
I guess this is because the loop in that case is the first, but I mean it’s also the last right? So why dosn’t both contents inside first and last
conditional show?
In my code they both execute if there is only one element in friendslist. Here is a test you can run in the shell where maybe you can figure out what isn’t working:
$ ./manage.py shell
>>> from django import template
>>> t = template.Template("""{% for f in friendslist %}
{% if forloop.first %}
First of the loop
{% endif %}
{{ f }}
{% if forloop.last %}
Last of the loop
{% endif %}
{% endfor %}""")
>>> c = template.Context({'friendslist' : ['one element',]})
>>> t.render(c)
First of the loop
one element
Last of the loop
couldn’t you just use an “or” tag like {% if forloop.last or friendlist.count == 1 %}
{% for f in friendslist %}
{% if forloop.first %}
// display something
{% endif %}
// display stuff
{% if forloop.last or friendlist.count == 1 %}
// display something
{% endif %}
{% endfor %}
You can also use ”not” in template to solve this. It works even there is just an item in the list.
{% for friend in friendslist %}
{% if not forloop.last %}
// display something
{% endif %}
{% if forloop.last %}
// display something
{% endif %}
{% endfor %}
Exemplifying the accepted answer for when you need to access a nested json that contains arrays of jsons, and get only the first element.
In the example below, in regards to users’ addresses, I want to show only the phone number of the first phone registered in the user profile.
Example users
json that will be passed to the HTML template
{
"name": "user1",
"birthdate": "date1",
"phones": [
{
"number": "111111111",
"type": "type1"
},
{
"number": "222222222",
"type": "type2"
}
],
}
HTML file to render this example in a table, using Jinja:
<table id="users_table" class="table table-hover table-sm">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Username</th>
<th scope="col">Birthdate</th>
<th scope="col">Phone</th>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr>
<th scope="row">{{ forloop.counter }}</th>
<td>{{ user.name }}</td>
<td>{{ user.birthdate }}</td>
{% for phone in user.phones %}
{% if forloop.first %}
<td> {{ phone.number }}</td>
{% endif %}
{% endfor %}
</tr>
</tbody>
</table>