I've been using those tricks for a while and find then awesomely useful.
First the more obvious. When styling navigation it's sometime useful to have a way to distinguish first and last elements, to eliminate a border for example.
CSS provide handy selectors expressions (:first-child and :last-child) to achieve this without pain. But were would the fun be without pain ?
To rectify the situation Microsoft decided nobody needed such selectors and didn't implement them in Internet Explorer.
So a sure way to do it in a for loop is like this;
{% for item in object_list %}
{% if forloop.first %}<ul>{% endif %}
<li>{% if forloop.first or forloop.last %} class="{% if forloop.first %}first{% else %}last{% endif %}"{% endif %}>
{{ item }}
</li>
{% if forloop.last %}</ul>{% endif %}
{% endfor %}
*Edit: Updated code. Thanks to Aidas Bendoraitis for his more fail safe approach.
* NOTE: Both "if forloop..." should be inside the LI tag like this, where the attributes goes. My code highlight doesn't seem to like it however .. the whole line disappear when I try to put it at the right place.
That way the first and last element are easily accessible with the .first and .last classes, even in a retarded browser.
The other trick is a bit more useful.
Let's take again or nav example from above but we want to create a anchor links list. How to easily create unique and related anchor names ? Easy: slugify.
Slugify is a nice template tag that convert a string into a URL friendly string to create readable URLs.
But it's easy to use it to create anchors too;
<ul>
{% for item in object_list %}
<li>
<a href="#{{ item.name|slugify }}">{{ item.name }}</a>
</li>
{% endfor %}
</ul>
Then when you cycle through the object link you can create the corresponding anchor as easily:
{% for item in object_list %}
<h2><a name="{{ item.name|slugify }}">{{ item.name }}</a></h2><h2>
<div>{{ item.body }}</div>
{% endfor %}
</h2>
That's it !
There's a typo in the forloop.first code. You never reference forloop.last
@Paul
Fixed it, thanks !
There are two problems with your first approach. If object_list is empty, then you'll get an empty UL tag (that is invalid). If object_list has just one element, then you will have to a LI with two class definitions (that is also invalid). To fix this, you would need to write such code:
{% for item in object_list %} {% if forloop.first %}<ul>{% endif %} <li>{% if forloop.first or forloop.last %} class="{% if forloop.first %}first{% else %}last{% endif %}"{% endif %}> {{ item }} </li> {% if forloop.last %}</ul>{% endif %} {% endfor %}