计算 django/python 中的月度数据
Calculate monthwise data in django/python
我得到的输入是 start_date 和 end_date,现在我想获取基于 start_date 和 end_date 之间月份的数据。如何在 python/django 中完成?
我正在获取格式为 -
的日期
start_date = '2021-5-5' #YYYY-MM-DD format
end_date = '2021-6-5'
所需结果-
result = [
{
'month' : 'may',
'data' : data_for_may # from date 5th of may to 31st of may
},
{
'month' : 'june',
'data' : data_for_june # from date 1st of june to 5th of june
}
]
首先,您需要将字符串转换为日期:
start_date = datetime.strptime(start_date , '%Y-%m-%d')
end_date = datetime.strptime(end_date , '%Y-%m-%d')
然后您可以在每个月进行迭代以填充您的 results
数组:
start_date = datetime.datetime.strptime(start_date, '%Y-%m-%d')
end_date = datetime.datetime.strptime(end_date, '%Y-%m-%d')
all_data = User.objects.filter(last_login__date__range=[start_date, end_date])
results = []
while start_date.year < end_date.year or start_date.month <= end_date.month:
results.append({
'month': start_date.strftime('%B'),
'year': start_date.strftime('%Y'),
'data': all_data.filter(last_login__date__month=start_date.month, last_login__date__year=start_date.year)
})
# Increment the start_date by one month using the dateutil library
start_date = start_date + dateutil.relativedelta(months=+1)
注意:我编辑了我对此解决方案的第一个想法,并在我的 Django 项目中对其进行了测试。
根据您拥有的数据量,我会在单个查询中获取所有数据,按日期时间排序,然后将它们分组到 Python 中。以下片段说明了这个想法。
from itertools import groupby
data = User.objects.order_by('last_login')
result = []
for (year, month), data_per_month in groupby(data, key=lambda x: (x.last_login.year(), x.last_login.month())):
result.append({
'year': year,
'month': month,
'data': data_per_month
})
这可能会快速且轻松地适应 10,000 个对象的内存。但是,当获取数百万条记录时,您可能需要重新考虑。
我认为你最好这样做:
from datetime import datetime
from django.db.models import Count
from django.contrib.auth.models import User
start_date = datetime.strptime('2021-5-5' , '%Y-%m-%d')
month_end_date = datetime.strptime('2021-6-5' , '%Y-%m-%d')
# SELECT year(last_login), month(last_login), count(*)
# FROM auth_user
# GROUP BY year(last_login), month(last_login)
# ORDER BY year(last_login), month(last_login)
qs = (User.objects.values('last_login__month', 'last_login__year')
.annotate(data=Count('*'))
.order_by('last_login__year', 'last_login__month'))
# WHERE last_login ...
qs = qs.filter(last_login__range=[start_date, month_end_date])
result = []
for item in qs:
result.append({
# get pretty name i.e "January"
'month': datetime(1900, item['last_login__month'] , 1).strftime('%B'),
'data': item['data']
})
result # [{'month': 'May', 'data': 81}, {'month': 'June', 'data': 15}])
为什么我觉得这个更好? (超过提供的其他答案)
每年每个月只有 1 条记录,容易 quantify/predict,性能更好。
顺便给你写了测试;)
https://gist.github.com/kingbuzzman/0197da03c52ae9a798c99d0cf58c758c#file-month_data-py-L82-L133
作为要点内的评论,我提供了有关如何使用 docker
进行测试的示例
我得到的输入是 start_date 和 end_date,现在我想获取基于 start_date 和 end_date 之间月份的数据。如何在 python/django 中完成?
我正在获取格式为 -
的日期start_date = '2021-5-5' #YYYY-MM-DD format
end_date = '2021-6-5'
所需结果-
result = [
{
'month' : 'may',
'data' : data_for_may # from date 5th of may to 31st of may
},
{
'month' : 'june',
'data' : data_for_june # from date 1st of june to 5th of june
}
]
首先,您需要将字符串转换为日期:
start_date = datetime.strptime(start_date , '%Y-%m-%d')
end_date = datetime.strptime(end_date , '%Y-%m-%d')
然后您可以在每个月进行迭代以填充您的 results
数组:
start_date = datetime.datetime.strptime(start_date, '%Y-%m-%d')
end_date = datetime.datetime.strptime(end_date, '%Y-%m-%d')
all_data = User.objects.filter(last_login__date__range=[start_date, end_date])
results = []
while start_date.year < end_date.year or start_date.month <= end_date.month:
results.append({
'month': start_date.strftime('%B'),
'year': start_date.strftime('%Y'),
'data': all_data.filter(last_login__date__month=start_date.month, last_login__date__year=start_date.year)
})
# Increment the start_date by one month using the dateutil library
start_date = start_date + dateutil.relativedelta(months=+1)
注意:我编辑了我对此解决方案的第一个想法,并在我的 Django 项目中对其进行了测试。
根据您拥有的数据量,我会在单个查询中获取所有数据,按日期时间排序,然后将它们分组到 Python 中。以下片段说明了这个想法。
from itertools import groupby
data = User.objects.order_by('last_login')
result = []
for (year, month), data_per_month in groupby(data, key=lambda x: (x.last_login.year(), x.last_login.month())):
result.append({
'year': year,
'month': month,
'data': data_per_month
})
这可能会快速且轻松地适应 10,000 个对象的内存。但是,当获取数百万条记录时,您可能需要重新考虑。
我认为你最好这样做:
from datetime import datetime
from django.db.models import Count
from django.contrib.auth.models import User
start_date = datetime.strptime('2021-5-5' , '%Y-%m-%d')
month_end_date = datetime.strptime('2021-6-5' , '%Y-%m-%d')
# SELECT year(last_login), month(last_login), count(*)
# FROM auth_user
# GROUP BY year(last_login), month(last_login)
# ORDER BY year(last_login), month(last_login)
qs = (User.objects.values('last_login__month', 'last_login__year')
.annotate(data=Count('*'))
.order_by('last_login__year', 'last_login__month'))
# WHERE last_login ...
qs = qs.filter(last_login__range=[start_date, month_end_date])
result = []
for item in qs:
result.append({
# get pretty name i.e "January"
'month': datetime(1900, item['last_login__month'] , 1).strftime('%B'),
'data': item['data']
})
result # [{'month': 'May', 'data': 81}, {'month': 'June', 'data': 15}])
为什么我觉得这个更好? (超过提供的其他答案)
每年每个月只有 1 条记录,容易 quantify/predict,性能更好。
顺便给你写了测试;)
https://gist.github.com/kingbuzzman/0197da03c52ae9a798c99d0cf58c758c#file-month_data-py-L82-L133
作为要点内的评论,我提供了有关如何使用 docker
进行测试的示例