Regroup vs. IfChanged in Django templates
This might be one of those things that is obvious to everyone but me, but I have a tendency to forget about Django’s regroup functionality. In this particular case, I wanted to make an alphabetical list of page titles, separated by a headline for each letter of the alphabet represented. My first attempt used IfChanged:
[toggle code]
-
<ul>
-
{% for item in page.family %}
- {% ifchanged %}</ul><h2 id="{{item.title|first|upper}}">{{ item.title|first|upper }}</h2><ul>{% endifchanged %}
- <li><a href="{{ item.url }}">{{ item.title }}</a></li>
- {% endfor %}
-
{% for item in page.family %}
- </ul>
I should have realized I was doing something wrong when I had to put in an empty list (before the letter “A”) to make it worked with IfChanged. It only became obvious for me, though, when I tried to add a “top” link at the bottom of each section of the alphabet. IfChanged wasn’t going to be able to handle it, because the letter “A” shouldn’t have a “top” link above it. I could use forloop.first, but then the IfChanged section would change between the first A item and the second A item, resulting in two headlines for the letter A.
I went to the Django template language for template authors page to see if there was a solution; there was (IfChanged can take a variable name) but I noticed regroup and wondered if it might be more appropriate. I’ve used it before, but not with filters. The documentation doesn’t mention using filters with the “by” portion of regroup, but I thought I’d flail around a bit. Turns out it works. If I “regroup page.familyIndex by title|first|upper as letters” I get a listing of each first letter represented in the titles.
[toggle code]
- {% regroup page.family by title|first|upper as letters %}
-
{% for letter in letters %}
- <h2 id="{{ letter.grouper }}">{{ letter.grouper }}</h2>
-
<ul>
-
{% for item in letter.list %}
- <li><a href="{{ item.url }}">{{ item.title }}</a></li>
- {% endfor %}
- <li class="topper"><a href="#top">(top)</a></li>
-
{% for item in letter.list %}
- </ul>
- {% endfor %}
No more empty list and no problem adding a special link at the bottom of each letter of the alphabet.
- Django template language for template authors
- “Django’s template language is designed to strike a balance between power and ease. It’s designed to feel comfortable to those used to working with HTML.”
More Django
- Django: fix_ampersands and abbreviations
- The fix_ampersands filter will miss some cases where ampersands need to be replaced.
- Custom managers for Django ForeignKeys
- I’ve got one really annoying model for keywords. There’s one category of keywords that, by default, should not show up when used as a ForeignKey for most models. Key word: most.
- Fixing Django 1.2.4’s SuspiciousOperation on filtering
- When you get the message “Filtering by keyword not allowed” in Django 1.2.4, here’s one way to fix it.
- Reusing Django’s filter_horizontal
- Just as with pop-ups, it’s possible to use the built-in JavaScript for filtering multiple-selection popups on custom forms.
- Django formsets and date/time fields
- Date/Time fields in Django formsets appear to have incompatible default values, resulting in forms using them always looking as though they’ve got a new entry when they don’t.
- 25 more pages with the topic Django, and other related pages
