按日期分组记录并添加字段列表

时间:2016-04-11 20:56:59

标签: python django django-models django-queryset django-orm

我有以下型号:

class Book(models.Model):
    name = models.CharField(max_length=255)
    published = models.DateField()
    items_sold = models.IntegerField()

现在,我想按发布日期对所有图书进行分组,我希望SUM已售出的项目(items_sold)。另外,我想在输出中添加所有names的列表。所以我的预期输出看起来像这样:

[{'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转换为列表。 我可以稍后使用splitnames.split(separator))执行此操作,但我认为这不够节省,因为我的分隔符也可能是书名的一部分。 有什么建议吗?

1 个答案:

答案 0 :(得分:1)

没有提到您正在使用的数据库。但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'))

并且,这将聚合所有名称并将它们放入列表中。