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

问题描述 投票:2回答:4

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

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天的月份不会削减它我害怕,谢谢你的建议!

python django orm date
4个回答
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 param来更改.aggregate()字典的键。

dateutil的relativedelta可以处理数天,数周,数年甚至更多。一个很好的包,我将重写我的本土hax。


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


1
投票

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


1
投票

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

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

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