1

假设我们有模型:

class Category(models.Model):
  description = models.CharField(...)  # Ex: 'horror', 'classic', 'self-help', etc.


class Book(models.Model):
  category = models.ForeignKey(Category, ...)
  written_date = models.DateField(...)

我想做一个查询,最终会得到我每年每个类别的图书总数!像这样:

{
  '2019-01-01': { 'horror': 2, 'classic': 1},
  '2020-01-01': { 'horror': 2, 'classic': 1, 'self-help': 4},
  ...
}

我只能提出以下查询:

Book.objects \
.annotate(year=TruncYear('written_date')) \
.values('year', 'category__description') \
.order_by('year') \
.annotate(total=Count('id'))

然而,这只会让我

{
    {
        "category__description": "Horror",
        "year": "2019-01-01",
        "total": 2
    },
    {
        "category__description": "Classic",
        "year": "2019-01-01",
        "total": 1
    },
    {
        "category__description": "Horror",
        "year": "2020-01-01",
        "total": 2
    },
    ...
}

有没有办法通过 ORM 做到这一点?或者我必须通过直接操作结果来做到这一点?谢谢!

4

1 回答 1

1

您可以使用groupby[python-doc]对结果进行后处理:

from itertools import groupby
from operator import itemgetter

data = Book.objects.values(
    'category__description'
    year=TruncYear('written_date'),
).annotate(
    total=Count('id')
).order_by('year', 'category__description')

result = {
    yrs: {r['category__description']: r['total'] for r in rs}
    for yrs, rs in groupby(data, itemgetter('year'))
}
于 2021-03-18T22:58:02.800 回答