Django: Listing queryset results under alphabetical headings
I'm trying to list the results from a query of 'Articles' under alphabetical headings based of the Article Title, eg:
A
- Apples
- Anteaters
B
- Bees
- Bats
etc
I know I could do this manually with querysets and filters within the view but is there a more pythonic approach to this? My initial thought was a pair of for loops within the template, one with the alphabet and the other with the articles, with something like {% if article.startwith({{ letter}}) %} but I don't think that is included with the Django templating language.
Model:
class Article(models.Model):
title = models.CharField(max_length=200)
tagline = models.CharField(max_length=75, blank=False, default='Required')
author = models.ForeignKey(
get_user_model(),
on_delete=models.SET_NULL,
null = True
)
created = models.DateTimeField(auto_now_add=True)
department = models.ForeignKey(Department, on_delete=models.SET_NULL, null=True, blank=True)
tags = TaggableManager()
banner_image = models.ImageField(upload_to='wiki_images/banners', null=True, blank=True)
body = models.TextField()
I also considered the Django regroup tag but struggling to understand how to pass it the first letter of each articles title.
Running Django 3.1 on this project. edit: Typo
Using regroup is a good idea!
But to have something to group on we also need to annotate our queryset with the first letter to have something to group on.
try this:
from django.db.models.functions import Substr, Upper
articles = Article.objects.annotate(first_letter=Upper(Substr('title', 1, 1)))
Then in template
{% regroup articles by first_letter as first_letter_articles %}
{% for first_letter in first_letter_articles %}
<li>{{ first_letter.grouper }}
<ul>
{% for article in first_letter.list %}
<li>{{ article.title }}</li>
{% endfor %}
</ul>
</li>
{% endfor %}