【问题标题】:Django Python - query count for the month and the past 6 monthsDjango Python - 本月和过去 6 个月的查询计数
【发布时间】:2019-04-08 04:11:52
【问题描述】:

我正在使用 Django 1.10.5 和 python 3.6

我有以下模型类:

class PublishedRecordedActivity(models.Model):
    published_details = models.ForeignKey(PublishedDetails, null=True, blank=True, on_delete=models.CASCADE)
    timestamp_added = models.DateTimeField(auto_now_add=True)
    activity_type = models.IntegerField(null=False, blank=False, default=1)

我想计算当前月份以及过去 6 个月中每个活动类型(1、2、3 或 4)的记录数。

例如,整个当月(2019 年 4 月)的计数。

一个月前(2019 年 3 月整月)的计数。

两个月前的计数(2019 年 2 月的整个月份)等。

我可以编写计数查询,但我不确定如何为每个月添加过滤器。

这是我的查询:

test_count = PublishedRecordedActivity.objects.filter(activity_type=1).count

【问题讨论】:

    标签: python django count


    【解决方案1】:

    首先,找出您要过滤的月份。为此,请使用 dateutil 包中的 relativedelta 函数

    In [33]: from datetime import datetime                                                                                                                                                                             
    
    In [34]: from dateutil.relativedelta import relativedelta                                                                                                                                                          
    
    In [35]: months_before = 6                                                                                                                                                                                         
    
    In [36]: now = datetime.utcnow()                                                                                                                                                                                   
    
    In [37]: now                                                                                                                                                                                                       
    Out[37]: datetime.datetime(2019, 4, 8, 5, 6, 42, 300424)
    
    In [38]: from_datetime = now - relativedelta(months=months_before)                                                                                                                                                 
    
    In [39]: from_datetime                                                                                                                                                                                             
    Out[39]: datetime.datetime(2018, 10, 8, 5, 6, 42, 300424)
    
    In [40]: modified_from_datetime = from_datetime.replace(day=1, hour=0, minute=0, second=0, microsecond=0)                                                                                                          
    
    In [41]: modified_from_datetime                                                                                                                                                                                    
    Out[41]: datetime.datetime(2018, 10, 1, 0, 0)
    

    然后在您的过滤器中使用 modified_from_datetime 变量和 gte

    PublishedRecordedActivity.objects.filter(activity_type=1, <b>timestamp_added__gte=modified_from_datetime</b>)

    完整片段

    from datetime import datetime
    from dateutil.relativedelta import relativedelta
    
    months_before = 6
    now = datetime.utcnow()
    from_datetime = now - relativedelta(months=months_before)
    modified_from_datetime = from_datetime.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
    
    PublishedRecordedActivity.objects.filter(activity_type=1, timestamp_added__gte=modified_from_datetime)
    

    更新-1

    使用分组功能,

    from django.db.models.functions import TruncMonth
    from django.db.models.aggregates import Count
    
    aggregated = PublishedRecordedActivity.objects.filter(
        activity_type=1).annotate(month=TruncMonth('timestamp_added')).values('month').annotate(sum_by_month=Count('month'))
    

    【讨论】:

    • 谢谢,但您的回答给了我过去 6 个月的总数。我正在寻求过去 6 个月中每个单独月份的计数。
    • 查看我的UPDATE-1 部分
    • 非常感谢!您提供的 update-1 解决了这个问题!
    【解决方案2】:

    您可以使用 Django 的 annotateTruncMonthCount 数据库函数获取每月的汇总值。下面给出使用示例

    from django.db.models.functions import TruncMonth
    
    aggregated = PublishedRecordedActivity.objects.filter(activity_type=1).annotate(month=TruncMonth('timestamp_added').values('month').annotate(sum_by_month=Count('id'))
    

    这将为您提供特定活动类型的每月汇总计数。您可以在timestamp_added 字段上添加其他过滤器应用时间范围。

    如果您只想汇总过去 6 个月的数据,请不要遵循。

    from datetime import date, timedelta
    current_date = date.today()
    months_ago = 6
    six_month_previous_date = current_date - timedelta(days=(months_ago * 365 / 12))
    
    aggregated = PublishedRecordedActivity.objects.filter(activity_type=1, timestamp_added__gte=six_month_previous_date).annotate(month=TruncMonth('timestamp_added').values('month').annotate(sum_by_month=Count('id'))
    

    months_ago 替换为您想要的月份汇总

    这会对你有所帮助。如果需要进一步帮助,请将 cmets 放在下面

    【讨论】:

    • 这将按月返回计数。即 2019 年 1 月,计数:2; 2/2019,计数:5; .... 12/2019,计数:6 ....
    • 使用您的建议,我如何将过滤器应用于 timestamp_added 以表示 4 个月前?
    • 我已经更新了我的答案并进行了调查。它返回按月分组的前六个月聚合值,并带有特定的activity_type
    • 这将分别返回您每个月的计数。
    猜你喜欢
    • 1970-01-01
    • 2019-04-09
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-29
    • 1970-01-01
    相关资源
    最近更新 更多