问题
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
回答1:
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})
回答2:
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.
来源:https://stackoverflow.com/questions/49828916/django-rest-framework-regroup-queryset-by-a-category