Django: 按日期分组(日、月、年)
Django: 按日期分组(日、月、年)
我有一个简单的模型,像这样:
class Order(models.Model): created = model.DateTimeField(auto_now_add=True) total = models.IntegerField() # monetary value
我想输出按月份分解的:
- 每个月有多少销售量(
COUNT
) - 合计价值(
SUM
)
我不确定最好的方法是什么。我看过一些相当吓人的额外选择查询,但我简单的思路告诉我,我最好只是迭代数字,从一个任意的起始年/月开始,一直计数到当前月份,然后丢弃简单查询过滤该月份的数据。更多的数据库工作 - 开发者的压力更小!
对你来说最有意义的是什么?我能否以一种简便的方式返回一个快速的数据表?或者我的笨方法可能是最好的主意?
我正在使用Django 1.3。不确定他们最近是否添加了更好的GROUP_BY
方法。
Django: Group by date (day, month, year)问题的出现原因是Django在1.10版本及以上中将extra方法标记为不久后将被弃用。为了解决这个问题,可以使用TruncMonth函数来进行分组。
在Django 1.10及以上版本中,可以使用以下代码来实现按月份分组:
from django.db.models.functions import TruncMonth from django.db.models import Count Sales.objects .annotate(month=TruncMonth('created')) # Truncate to month and add to select list .values('month') # Group By month .annotate(c=Count('id')) # Select the count of the grouping .values('month', 'c') # (might be redundant, haven't tested) select month and count
在旧版本的Django中,可以使用以下代码来实现按月份分组:
from django.db import connection from django.db.models import Sum, Count truncate_date = connection.ops.date_trunc_sql('month', 'created') qs = Order.objects.extra({'month':truncate_date}) report = qs.values('month').annotate(Sum('total'), Count('pk')).order_by('month')
如果想要将日期转换为合适的datetime.date格式,可以使用xx.month.date()
或者在模板中使用{{ row.month.date }}
。
需要注意的是,如果使用extra方法,要注意该方法可能会被弃用,应该尽量避免使用。在Django文档中有相关说明。
如果想要按照特定的日期间隔进行分组,比如按照7天进行分组,可以使用其他方法来实现。
另外,需要注意的是,如果Django的USE_TZ设置为True,使用TruncMonth函数和date_trunc_sql函数得到的结果可能不完全相同。TruncMonth函数会先将时间戳转换为TIME_ZONE设置指定的时区,然后再进行截断,而date_trunc_sql函数则是直接对数据库中的原始UTC时间戳进行截断。
以上是关于Django: Group by date (day, month, year)问题的原因以及解决方法的整理。
问题的出现原因是数据跨越多年时,使用ExtractMonth函数无法正确地按年份进行分组。因为每年的月份都是相同的,导致它们即使年份不同也会被分组在一起。
解决方法是使用ExtractYear函数来同时分组年份和月份。下面是使用ExtractYear和ExtractMonth函数的示例代码:
from django.db.models.functions import ExtractYear, ExtractMonth Sales.objects .annotate(year=ExtractYear('timestamp')) .annotate(month=ExtractMonth('timestamp')) .values('year', 'month') .annotate(count=Count('id')) .values('year', 'month', 'count')
这样就可以按年份和月份同时进行分组,正确地统计每个月份的销售数量了。
Django: 按日期分组(天、月、年)
问题出现的原因:在使用Django 1.10.6和Postgres数据库时,按照月份分组的代码未能正常工作,需要添加order_by()方法才能解决。
解决方法:
1. 导入TruncMonth方法和Count方法:
from django.db.models.functions import TruncMonth
2. 使用annotate方法将时间戳字段按照月份截断并添加到select列表中:
Sales.objects .annotate(month=TruncMonth('timestamp'))
3. 使用values方法按照月份分组:
.values('month')
4. 使用annotate方法选择分组的计数:
.annotate(c=Count('id'))
5. 使用order_by方法对结果进行排序:
.order_by()
这样就能够按照日期(天、月、年)进行分组了。
参考文档:docs.djangoproject.com/en/1.11/topics/db/aggregation/…
一些用户评论:
- TruncDate可以按照日期(天)进行分组。
- 这个方法返回了我想要展示的准确输出。谢谢!
- .annotate(month=TruncMonth('timestamp'))
中的timestamp是一个Python类型,这样命名有点混淆。
- Postgres数据库需要添加order_by才能正常工作,不知道为什么,但这就是问题所在。在文档上花了2个小时终于解决了。:( 谢谢。
- 我的数据库非常庞大,有几百万条记录。在实际应用中使用起来非常慢。有什么建议吗?
解决方法提供了按照日期进行分组的代码示例,并且指出了在使用Postgres数据库时需要注意的问题。对于需要对大型数据库进行操作的用户,可能需要优化数据库或者使用其他方法来提高性能。