I\'m trying to group records by the character of name
field of each record and limit the items in each group, here is what I have came up with:
desi
For Django REST you can refer,
Get Response Group by Alphabet
{
"A": [
"Adelanto",
"Azusa",
"Alameda",
"Albany",
"Alhambra",
"Anaheim"
],
"B": [
"Belmont",
"Berkeley",
"Beverly Hills",
"Big Sur",
"Burbank"
],
......
}
first ordering and then filtering is overkill and in vain. you should only order the data you need. Otherwise you are ordering all rows by name and then filtering and slicing what you need.
I would do:
User.objects.filter(name__startswith=desired_letter).order_by("name")[:10]
and .all()
was redundant.
From the comment in the other answer:
I was actually looking for a way to implement Group By First Character in django orm
I would do it in following 3 steps:
Annotate each record with first letter of the name
field. For that you could use Substr function along with Lower
from django.db.models.functions import Substr, Lower
qs = User.objects.annotate(fl_name=Lower(Substr('name', 1, 1)))
Next, group all the records with this first letter and get the count of ids. This can be done by using annotate with values:
# since, we annotated each record we can use the first letter for grouping, and
# then get the count of ids for each group
from django.db.models import Count
qs = qs.values('fl_name').annotate(cnt_users=Count('id'))
Next, you can order this queryset with the first letter:
qs = qs.order_by('fl_name')
Combining all these in one statement:
from django.db.models.functions import Substr, Lower
from django.db.models import Count
qs = User.objects \
.annotate(fl_name=Lower(Substr('name', 1, 1))) \
.values('fl_name') \
.annotate(cnt_users=Count('id')) \
.order_by('fl_name')
At the end, your queryset would look something like this. Do note, that I converted first character to lower case while annotating. If you don't need that, you can remove the Lower
function:
[{'fl_name': 'a', 'cnt_users': 12},
{'fl_name': 'b', 'cnt_users': 4},
...
...
{'fl_name': 'z', 'cnt_users': 3},]
If, you need a dictionary of letter and count:
fl_count = dict(qs.values('fl_name', 'cnt_users'))
# {'a': 12, 'b': 4, ........., 'z': 3}