penlightment
penlightment

Reputation: 71

Django Rest Framework regroup queryset by a category

In the current project that i'm working on, i need to regroup (group) a queryset by category and put contents with same category in a list all provided together. I have the following model structure:

class Category(models.Model):
    title = models.CharField(max_length=255)

class Item(models.Model):
   title = models.CharField(max_length=255)
   category = models.ForeignKey(to="Category", verbose_name=_('category'), related_name='items',
                                 on_delete=models.SET_NULL, null=True, blank=True)

I would like the output serialized result to be like:

    {
     "category_title_1":[
        {
          "id": 1,
          "title" : "something",
        },
        {
          "id": 2,
          "title": "something else",
        }
      ],
    "category_title_2": [
      {
       "id": 3,
       "title": "another string",
      }, 
      {
       "id": 4,
       "title": "and yet another title",
      }
    ]
  }  

I know i can always iterate over the queryset and group them manually, i'm wondering if there is a native efficient way to do this.

Thanks

Upvotes: 3

Views: 3024

Answers (2)

Will Keeling
Will Keeling

Reputation: 23004

I don't believe this is possible using the ORM itself, although as Guybrush mentions, itertools.groupby can be used to achieve this - and in a reasonably elegant way.

from itertools import groupby
from operator import itemgetter
from rest_framework.response import Response

items = Item.objects.values('category__title', 'id', 'title').order_by('category__title')
rows = groupby(items, itemgetter('category__title'))
return Response({c_title: list(items) for c_title, items in rows})

Upvotes: 9

Guybrush
Guybrush

Reputation: 2780

If your goal is to regroup them in a template, have a look at https://docs.djangoproject.com/en/2.0/ref/templates/builtins/#regroup Note that you'll have to sort your objects by category first, as regroup relies on that order to produce correct output.

If your goal is to regroup them in the code (as opposed to templates), you can rely on itertools.groupby (see https://docs.python.org/3/library/itertools.html#itertools.groupby). Again, you'll need to join and sort your data first.

Upvotes: 1

Related Questions