返回Django视图集中一列按另一列分组的值列表



假设我有一个模型:

class Entry(models.Model):
content = models.CharField(max_length=140)
email = models.EmailField()
upload_date = models.DateTimeField(default=timezone.now)
class Meta:
db_table = 'entries'

我想要实现的是,视图集返回每个电子邮件的contentupload_date值列表(因为许多条目可以具有相同的电子邮件值(,如下所示:

[
{
"email": "address1@test.test",
"entries": [
{
"upload_date": "2020-09-03",
"content": "test content 1"
},
{
"upload_date": "2020-09-02",
"content": "test content 2"
},
...
]
},
{
"email": "address2@test.test",
"entries": [
{
"upload_date": "2020-09-03",
"content": "test content 11"
},
{
"upload_date": "2020-09-02",
"content": "test content 12"
},
...
]
},
...
]

我试着摆弄.values().annotate(),但没有成功。

使用groupbyitertools函数快速回答:


def entry_converter(entry):
return {'upload_date': entry.upload_date, 'content': entry.content}

def grouping_key(entry):
return entry.email

from itertools import groupby
entries = Entry.objects.order_by('email')
grouped_entries = [dict(email=key, entries=list(map(entry_converter, group))) for key, group in groupby(entries, key=grouping_key)]

更新1

与DRF ViewSet 集成

def entry_converter(entry):
return {'upload_date': entry.id, 'content': entry.id}

def grouping_key(entry):
return entry.email

def group_entries(entries):
return [
dict(email=key, entries=list(map(entry_converter, group))) for key, group in groupby(entries, key=grouping_key)
]

class EntrySerializer(ModelSerializer):
class Meta:
model = Entry
fields = '__all__'

class EntryViewSet(ModelViewSet):
queryset = Entry.objects.all()
serializer_class = EntrySerializer
def list(self, request, *args, **kwargs):
queryset = self.get_queryset().order_by('email')
data = group_entries(queryset)
page = self.paginate_queryset(data)
if page is not None:
return self.get_paginated_response(page)
return Response(data)

请记住,我没有使用ModelViewSet的.filter_queryset()方法,因为它可能会通过添加错误的排序或错误的筛选来修改查询集。因为groupby函数需要排序后的数据作为输入。此外,我还没有重写ModelSerializer类来推广ModelViewSet.list()方法,因为它可能会产生额外的复杂性。

最新更新