Django按两场的数量计算和分组

问题描述 投票:1回答:1

我有这样的模型:

CLASS_TYPE = ( ("A","A Class"), ("B", "B Class") , ("C", "C Class") , ("D", "D Class") ) 

class Student(models.Model):
   systemId    = models.CharField(max_length=15, unique=True )
   studentNo   = models.CharField(max_length=15, unique=True )
   country     = models.CharField(max_length=50)
   clasType    = models.CharField(max_length=2, choices=CLASS_TYPE )
   recordDate = models.DateField() 
...

并且有很多记录。

我很有意思只有两个字段“country”和“classType”。 根据国家和总和,我想计算所有班级类型。

我想从list模型中获取这个字典的Student

[
    { "country":"USA" , "A" : Count_Of_A_Class_in_USA , "B" : Count_Of_B_Class_in_USA , "C" : countCinUSA , "D": count_D_in_USA , "Total" : total_students_in_USA } ,
    {"Country":"England" , "A" : A_in_England ...., "C":C_in_England... , "Total" : students_in_England }
]

我怎么能得到这个?

django group-by count annotations aggregate
1个回答
2
投票

我们可以首先根据country和per clasType查询获得Students的数量:

qs = Student.objects.values('country', 'clasType').annotate(
    n=Count('pk')
).order_by('country', 'clasType')

现在我们可以使用itertools.groupby [Python-doc]将这些词典组合在一起更紧凑的词典中:

from itertools import groupby
from operator import itemgetter

data = [
    {'country': c, ** { li['clasType']: li['n'] for li in l } }
    for c, l in groupby(qs, itemgetter('country'))
]

但是我们仍然需要做“补丁”:有可能一个国家没有所有的clasTypes,我们可能想为这些添加0s,而且我们需要计算总数。我们可以这样做:

for subd in data:
    total = 0
    for ct, _ in CLASS_TYPE:
        total += subd.setdefault(ct, 0)
    subd['Total'] = total

现在data包含一个字典列表,每个字典都有一个'country''Total'密钥,每个CLASS_TYPE一个密钥和StudentCLASS_TYPE数量。

© www.soinside.com 2019 - 2024. All rights reserved.