按月和季度的Django / python日期聚合

时间:2011-02-01 12:02:22

标签: python django orm date

我正在编写一项功能,要求在不同时间(周,月,季度等)的项目的平均价格。这是模型:

class ItemPrice(models.Model):
    item = models.ForeignKey(Item)
    date = models.DateField()
    price = models.FloatField()

此模型跟踪项目的价格随着时间的推移,新项目以频繁但非常规的间隔添加。 在过去一周内找到平均price非常容易:

ItemPrice.objects.filter(item__id = 1)
    .filter(date_lt = TODAY)
    .filter(date_gte = TODAY_MINUS_7_DAYS)
    .filter(date_.aggregate(Avg('value'))

一周总有7天,但月和季度呢?他们有不同的天数......?

谢谢!

编辑: 该应用程序是为一个金融机构,30天的月份不会削减它我害怕,谢谢你的建议!

4 个答案:

答案 0 :(得分:2)

解决方案分为两部分,首先使用django ORM的aggregation函数,第二部分使用python-dateutil

from dateutil.relativedelta import relativedelta

A_MONTH = relativedelta(months=1)

month = ItemPrice.objects \
    .filter(date__gte = date - A_MONTH) \
    .filter(date__lt = date) \
    .aggregate(month_average = Avg('price'))

month等于:

{'month_average': 40}

值得注意的是,您可以通过更改month参数来更改.aggregate()字典的键。

dateutil的亲戚可以处理数天,数周,数年等等。一个很棒的套餐,我将重写我的本土hax。

答案 1 :(得分:2)

import datetime
from dateutil import relativedelta, rrule  

obj = self.get_object()  
datenow = datetime.datetime.now() 

quarters = rrule.rrule(
        rrule.MONTHLY,
        bymonth=(1, 4, 7, 10),
        bysetpos=-1,
        dtstart=datetime.datetime(datenow.year, 1, 1),
        count=5)

    first_day = quarters.before(datenow)
    last_day = (quarters.after(datenow) - relativedelta.relativedelta(days=1))

    quarter = Payment.objects.filter(
        operation__department__cashbox__id=obj.pk,
        created__range=(first_day, last_day)).aggregate(count=Sum('amount'))

inspiration from there

答案 2 :(得分:1)

我会选择360-day calendar而不用担心这些小小的不准确之处。只需使用过去30天的“上个月平均值”和过去90天的“上一季度平均值”。

答案 3 :(得分:1)

首先,您对过去7天或上周感兴趣吗?如果答案是上周,则查询不正确。

如果超过您关注的“n”天,那么您的查询是正确的,我想您可以放松并使用30天一个月和90天一季度。