【问题标题】:Django - Group By with Date part aloneDjango - Group By 仅包含日期部分
【发布时间】:2011-07-12 13:02:41
【问题描述】:
MyModel.objects.filter(created_at__gte='2011-03-09', created_at__lte='2011-03-11').values('created_at','status').annotate(status_count=Count('status'))

上述查询与created_at 日期时间字段存在问题。是否可以调整上述查询以忽略时间值并在执行分组时单独使用日期值?

【问题讨论】:

    标签: python django django-models django-queryset


    【解决方案1】:

    您可以在 django 中使用额外的关键字轻松完成。

    MyModel.objects
    .filter(created_at__gte='2011-03-09', created_at__lte='2011-03-11')
    .extra({"created_at":"date_trunc('day', created_at)"}).values('created_at','status').annotate(status_count=Count('status'))
    

    date_trunc 是它需要的 postgres 函数,只指定了精度。

    【讨论】:

      【解决方案2】:

      这个问题我来得太晚了,但为了将来参考,我想指出这实际上是可以用原生 Django 实现的,如 https://stackoverflow.com/a/2283913 所述

      【讨论】:

      • .extra() 方法实际上添加了 DB 级别的调用,所以从技术上讲,这不是“原生 Django”。
      【解决方案3】:

      是的,这可以使用“额外”和数据库级别的日期格式化函数。 实施可以在例如找到django-qsstats-magic 包。

      【讨论】:

        【解决方案4】:

        我不确定 Django 的 ORM 是否可以在查询中间执行日期时间到日期的转换。不过,您可以先进行查询,获取结果,然后使用 Python groupby() 函数对返回的行进行排序。下面是一个按日期分组日期时间的小例子:

        from pprint import pprint
        from datetime import datetime
        from itertools import groupby
        
        rows = [('Frodo party', datetime(3018, 9, 22, 10, 38)),
                ('Nazgul defeat Rangers', datetime(3018, 9, 22, 11, 57)),
                ('Frodo finishes packing', datetime(3018, 9, 23, 10, 59)),
                ('Gandalf tames Shadowfax', datetime(3018, 9, 23, 13, 11)),
                ('Gandalf crosses the Isen', datetime(3018, 9, 24, 18, 46))]
        
        for key, values in groupby(rows, key=lambda row: row[1].date()):
            print('-')
            pprint(key)
            pprint(list(values))
        

        如您所见,您必须为 groupby() 提供一个 key 函数,该函数采用它正在分组的对象之一并提取分组应该发生的值 - 在这种情况下,它获取每行中的第二项带有[1],然后在其上调用Python datetime 方法date() 以提取没有小时和分钟的日期部分。脚本的输出看起来像这样(pprint() 函数只是一个花哨的“打印”语句,用于缩进输出,在您的 Django 代码中不需要它!):

        -
        datetime.date(3018, 9, 22)
        [('Frodo party', datetime.datetime(3018, 9, 22, 10, 38)),
         ('Nazgul defeat Rangers', datetime.datetime(3018, 9, 22, 11, 57))]
        -
        datetime.date(3018, 9, 23)
        [('Frodo finishes packing', datetime.datetime(3018, 9, 23, 10, 59)),
         ('Gandalf tames Shadowfax', datetime.datetime(3018, 9, 23, 13, 11))]
        -
        datetime.date(3018, 9, 24)
        [('Gandalf crosses the Isen', datetime.datetime(3018, 9, 24, 18, 46))]
        

        【讨论】:

          猜你喜欢
          • 2010-10-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-08-15
          • 1970-01-01
          • 2018-07-16
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多