我的Django模型中有下表:
Date | Field1 | Field2 | Field3 | Field4 | Field5 | Field6 |
05/01/2018 | 7 | 1 | 8 | 4 | 9 | 2 |
05/02/2018 | 9 | 2 | 1 | 1 | 6 | 2 |
05/03/2018 | 8 | 1 | 3 | 1 | 5 | 1 |
05/04/2018 | 7 | 1 | 8 | 4 | 9 | 2 |
05/05/2018 | 7 | 1 | 8 | 4 | 9 | 2 |
我想返回自定义时间段内具有最高总和的前3个字段的名称。
例如,如果我想获得前5个字段中的 NAMES ,这些字段在2018年5月2日至2018年5月4日之间的总和最高,则应返回以下内容:
“字段1,字段5,字段3”
因为:
Date | Field1 | Field2 | Field3 | Field4 | Field5 | Field6 |
05/02/2018 | 9 | 2 | 1 | 1 | 6 | 2 |
05/03/2018 | 8 | 1 | 3 | 1 | 5 | 1 |
05/04/2018 | 7 | 1 | 8 | 4 | 9 | 2 |
SUM | 24 | 4 | 12 | 6 | 20 | 5 |
我可以执行以下操作:
1)使用__dict__
2)遍历所有字段名称,通过过滤日期和使用.aggregate(SUM())汇总表中的值,并将结果放入{FieldNames:Sums}的字典中
3)最后,按值(总和)对字典进行排序,并提取与前3个值相对应的键(字段名称)。
这种方法似乎过于矫and过正,我想知道是否存在使用Querysets实现此目的的更Pythonic / Django风格的方法?
答案 0 :(得分:0)
我相信条件聚合可以解决这个问题;您将汇总每个字段的总和,例如...
https://docs.djangoproject.com/en/2.0/ref/models/conditional-expressions/#case
from django.db.models import Case, When, IntegerField
from django.db.models.functions import Cast
uglyquery = ModelName.objects.aggregate(
field_name_sum=Sum(
Case(
When(
Q(timestamp__lte=date.today() & Q(timestamp __gte=start_date)),
then=Cast('field_name',IntegerField()) # pretty sure the Cast is necessary
), output_field= IntegerField())
)
),
field_2_sum=....
)
将返回一个包含所有字段和总和的字典,然后可以对其进行排序。
现在,因为我们无法使用python from operator import itemgetter
对字典进行排序,所以我们有了...
How do I sort a dictionary by value?
sorted(uglyquery.items(), key=itemgetter(1))[3:6]
# slice the first three results and leave only the remaining that we are interested in
告诉排序后的函数以每个字段的总和进行排序,此方法以元组列表(即[('Field2',4), ('Field6',5), ...]
由于我们对最小值进行了切片,因此剩下的三个字段在该日期范围内的总和最高为6。 :)