Django按组取3的模型字段平均值

0 投票
2 回答
752 浏览
提问于 2025-04-17 21:01

我有大约6000个值。每个值都有一个叫做 total 的字段。我需要生成一个每3个元素的平均值(取整)的集合(分组)。

举个例子: 1 3 100 4 5 8 10 1 20 ...

想要的结果集: 35 6 10 ...

我的 models.py 文件看起来是这样的:

class resume(models.Model):
  total = models.DecimalField(max_digits=9, decimal_places=2,default=0)

我在想要在 views.py 中添加一些与 resume.objects.all().aggregate(Avg('total')) 相关的内容(在渲染的时候)。我看到的一些解决方案使用了SQL。有没有什么办法可以在django中做到这一点?

2 个回答

1

修复了:

from django.db.models import Avg
all_res = Resume.objects.all()
answer = [ all_res[(i*3):((i*3)+3)].aggregate(Avg('total') for i in range(all_res.count()/3)]

现在因为用了聚合函数,代码变得更简洁了。第一行从所有的简历中提取出总值。接下来,有个字符串理解的过程,它会对所有简历的前三分之一进行处理,计算从 i*3 到 (i*3)+3 这三个数字的和。假设 all_res 的开头是 [5, 4, 6, .....], 那么在列表理解的第一次循环中,i 的值会这样变化:

sum(all_res[(0*3):((0*3)+3)])/3
sum(all_res[0:3])/3
sum([5,4,6])/3
15/3
# 5

补充说明:我觉得这不是大问题,但如果你的数据库里没有 n 条记录,并且 n%3 = 0(我猜 6000 是个大概的数字),而你又非常需要每个数字都准确的话,那么你可以用 len(i*3:i*3+3) 来代替 3 来进行计算,因为如果切片的上限超出了范围,它会返回到列表的末尾。

2

你可能需要手动按照下面的步骤来操作:

# http://docs.python.org/2/library/itertools.html
def grouper(iterable, n, fillvalue=None):
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

def avg(xs):
    xs = [x for x in xs if x is not None]
    return sum(xs) / len(xs)

# Retrieve all `total` values as a flat list-like ValueListQuerySet.
values = resume.objects.all().values_list('total', flat=True)
avgs = [avg(xs) for xs in grouper(values, 3)]

撰写回答