我有以下模型:
class Book(models.Model):
name = models.CharField(max_length=255)
published = models.DateField()
items_sold = models.IntegerField()
现在,我想按出版日期对所有图书进行分组,并对已售商品 (items_sold
) 进行SUM
。此外,我想将所有名称
的列表添加到输出中。所以我的预期输出将如下所示:
[{'date': datetime.date(2015, 12, 14), 'total_sold': 5000, 'names': ['Book A', 'Book B']},
{'date': datetime.date(2016, 11, 4), 'total_sold': 10000, 'names': ['Book C']}, ... ]
我尝试使用annotate
解决这个问题:
Book.objects.values('date').annotate(total_sold=Sum('items_sold'))
但我不知道如何将名称列表放入结果中。 annotate
是正确的方法吗?有谁知道如何解决这个问题吗?
编辑:
感谢 Todor 的评论,我找到了使用自定义聚合的部分解决方案:
class Concat(models.Aggregate):
"""
Using SQLite `group_concat` function
"""
function = 'group_concat'
template = '%(function)s(%(field)s, "%(separator)s")'
现在我有这个查询:
Book.objects.values('date').annotate(total_sold=Sum('items_sold'), names=Concat('names', separator=',')
> [{'date': datetime.date(2016, 1, 5), 'total_sold': 5000, 'names': 'Book A, Book B'}, ...,]
现在的问题是书名被连接到字符串names
。我可以定义分隔符,但我不知道如何将 names
转换为列表。
我可以稍后使用 split
(names.split(separator)
) 来完成此操作,但我认为这还不够保存,因为我的分隔符也可能是书名的一部分。
有什么建议吗?
最佳答案
没有提及您正在使用哪个数据库。但Django 1.9提供了某些postgres specific aggregate functions例如ArrayAgg 在这里非常有用:
from django.contrib.postgres.aggregates import ArrayAgg
Book.objects.values('date').annotate(total_sold=Sum('items_sold'), names=ArrayAgg('name'))
并且,这将聚合所有名称并将它们放入一个列表中。
关于python - 按日期对记录进行分组并添加字段列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36559088/