如何在Django中高效地跨多个模型聚合?

1 投票
1 回答
846 浏览
提问于 2025-04-18 10:25

我遇到了一些复杂的情况,请耐心听我说。我有四个模型:

  1. 主类别(MainCategory)
  2. 类别(Category,指向主类别的外键)
  3. 猫(Cat,与类别有多对多关系)
  4. 狗(Dog,与类别有多对多关系)

我的一般 JSON 输出大概是这样的:

[ {name: 'coat_type',
   cat_count: 3,
   dog_count: 5,
   total_count: 8, 
   sub_cats: [ {name: 'furry', cat_count: 1, dog_count: 3, total_count: 4}, 
               {name: 'shaggy', cat_count: 2, dog_count: 2, total_count: 4} ],

  {name: 'facial_features', ... } ]

接下来是我的一系列查询,我觉得这效率不是太高:

output = []

for main_cat in MainCategory.objects.all():
    ...
    sub_cats = Category.objects.filter(main_category=main_cat)
    counts = sub_cats.annotate(
        cat_count = Count('cat', distinct=True),
        dog_count = Count('dog', distinct=True),
        #how do i aggregate total count here?
        #total_count = cat_count + dog_count 
    ).values('name', 'ip_count', 'doc_count', 'total_count')

    main_cat_dict = {
        'name': main_cat.name,
        'sub_cats': counts,
        ...
    }
    output.append(main_cat_dict)

我觉得子类别的聚合还可以,但问题是我还是得逐个遍历每个主类别。而且我不太确定怎么在每个子类别里面计算总数。

提前谢谢你们!

1 个回答

0

你可以这样做:

sub_cats = Category.objects.filter(main_category__in=MainCategory.objects.all())

然后就可以像之前那样进行注释和调用 values。当然,你可以先在 MainCategory 模型上进行过滤,以排除一些主要类别。

使用标准的 Django ORM,无法基于其他注释进行注释。要获取每个条目的总计数,最好在 Python 中进行一些后处理:

for d in sub_cats:
    d['total_count'] = d['cat_count'] + d['dog_count']

撰写回答