Django group object by the first character of a column

前端 未结 3 708
甜味超标
甜味超标 2021-02-15 15:42

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         


        
3条回答
  •  情书的邮戳
    2021-02-15 16:38

    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:

    1. 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)))
      
    2. 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'))
      
    3. 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}
    

提交回复
热议问题