【问题标题】:Django Group By Weekday?Django Group By Weekday?
【发布时间】:2013-06-19 17:40:28
【问题描述】:

我正在使用 Django 1.5.1、Python 3.3.x,并且不能为此使用原始查询。

对于使用日期__range 过滤器的查询集,有没有办法按工作日分组查询集?我正在尝试按工作日对结果进行分组,以获取介于任意两个日期之间的查询(可能相隔一年)。我知道如何get rows that match a weekday,但这需要用 7 个查询来敲击数据库,才能找出每个工作日的数据。

我已经尝试了几个小时来解决这个问题,尝试使用 __week_day 过滤器进行不同的调整,但没有任何效果。即使谷歌搜索也无济于事,这让我想知道这是否可能。如果可以的话,任何 Django 大师都知道怎么做?

【问题讨论】:

    标签: python django python-3.x django-1.5


    【解决方案1】:

    由于extra 已被弃用,这里有一种使用ExtractDayOfWeek 对星期几进行分组的新方法。

    from django.db.models.functions import ExtractWeekDay
    YourObjects.objects
        .annotate(weekday=ExtractWeekDay('timestamp')) 
        .values('weekday')                          
        .annotate(count=Count('id'))                  
        .values('weekday', 'count')   
    

    这将返回如下结果:

    [{'weekday': 1, 'count': 534}, {'weekday': 2, 'count': 574},.......}
    

    同样重要的是要注意 1 = 星期日和星期六 = 7

    【讨论】:

    • 和5个版本的django以后,增加了ExtractWeekDay关键字。注意:仍然需要在 django 1.5 中使用 .extra() 函数(按要求)。
    【解决方案2】:

    好吧,我做了一个算法,这个算法为你带来了从一周开始(星期一)到今天的所有记录

    例如,如果您的应用中有这样的模型:

    from django.db import models
    
    class x(models.Model):
            date = models.DateField()
    
    from datetime import datetime
    from myapp.models import x
    start_date = datetime.date(datetime.now())
    week = start_date.isocalendar()[1]
    day_week =start_date.isoweekday()
    days_quited = 0
    less_days = day_week
    while less_days != 1:
         days_quited += 1
         less_days -= 1
    
    week_begin = datetime.date(datetime(start_date.year,start_date.month,start_date.day-days_quited))
    
    records = x.objects.filter(date__range=(week_begin, datetime.date(datetime.now())))
    

    如果您在 6 月 17 日(星期一)和 6 月 22 日(今天)之间添加一些记录,您将看到所有这些记录,如果您添加更多记录,例如明天的日期或下周一的日期,您将看不到这些记录。

    如果你想要到现在为止的其他一周的记录,你只需要输入这个:

    start_date = datetime.date(datetime(year, month, day))
    records = x.objects.filter(date__range=(week_begin, datetime.date(datetime.now())))
    

    希望这会有所帮助! :D

    【讨论】:

    • 这只是一个日期范围,而不是一个分组。当日期范围跨越多个星期时,它将不起作用。
    • 嗯,我认为这相当于Model.objects.filter(date__week=week_number),多周你是指连续吗?
    【解决方案3】:

    您需要在选择中添加一个额外的工作日字段,然后在总和或平均聚合中按该字段分组。请注意,这将成为特定于数据库的查询,因为“额外”表示法会传递给 DB select 语句。

    给定模型:

    class x(models.Model):
        date = models.DateField()
        value = models.FloatField()
    

    然后,对于 mysql,使用 ODBC weekday 到 python datetime weekday 的映射:

    x.objects.extra(select={'weekday':"MOD(dayofweek(date)+5,7)"}).values('weekday').annotate(weekday_value=Avg('value'), weekday_value_std=StdDev('value'))
    

    请注意,如果您不需要将 MySql ODBC 工作日(1 = 星期日,2 = 星期一...)转换为 python 工作日(星期一为 0,星期日为 6),则不需要进行取模.

    【讨论】:

      【解决方案4】:

      对于这样的模型:

      class A(models.Model):
          date = models.DateField()
          value = models.FloatField()
      

      您可以使用查询:

      weekday     = {"w": """strftime('%%w', date)"""}
      qs = A.objects.extra(select=weekday).values('w').annotate(stat = Sum("value")).order_by()
      

      【讨论】:

        猜你喜欢
        • 2015-05-23
        • 1970-01-01
        • 2021-08-01
        • 2019-02-28
        • 2021-08-01
        • 2017-12-23
        • 1970-01-01
        • 1970-01-01
        • 2021-06-05
        相关资源
        最近更新 更多