【问题标题】:How can I filter a date of a DateTimeField in Django?如何在 Django 中过滤 DateTimeField 的日期?
【发布时间】:2010-11-22 00:12:29
【问题描述】:

我正在尝试过滤 DateTimeField 与日期进行比较。我的意思是:

MyObject.objects.filter(datetime_attr=datetime.date(2009,8,22))

我得到一个空的查询集列表作为答案,因为(我认为)我没有考虑时间,但我想要“任何时间”。

在 Django 中有一个简单的方法可以做到这一点吗?

我设置了日期时间,不是00:00

【问题讨论】:

标签: python django datetime filter django-queryset


【解决方案1】:

这样的查找在django.views.generic.date_based中实现如下:

{'date_time_field__range': (datetime.datetime.combine(date, datetime.time.min),
                            datetime.datetime.combine(date, datetime.time.max))} 

由于它非常冗长,因此计划使用__date 运算符改进语法。详情请查看“#9596 Comparing a DateTimeField to a date is too hard”。

【讨论】:

  • 使用范围:Q(created__gte=datetime.combine(created_value, time.min))
  • 看起来它将登陆 Django 1.9:github.com/django/django/commit/…
  • Django 1.9 中的新功能:Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))
【解决方案2】:
YourModel.objects.filter(datetime_published__year='2008', 
                         datetime_published__month='03', 
                         datetime_published__day='27')

//在cmets之后编辑

YourModel.objects.filter(datetime_published=datetime(2008, 03, 27))

不起作用,因为它创建了一个时间值设置为 0 的日期时间对象,因此数据库中的时间不匹配。

【讨论】:

  • 感谢您的回答!第一种选择不适用于日期时间字段。第二种选择有效;)。如果有人知道另一种方法,请回答
  • docs.python.org/library/datetime.html#datetime-objects 使用 datetime 模块 hrs,mins,secs 中的 datetime() 是可选的。第二个来自替换了 vars 的工作项目,您可以在文档中查看它是正确的
  • 我知道它是可选的,问题是我的 datetimefield 设置了时间,它不是 00:00
  • “第一个替代方法不适用于日期时间字段。”这会非常令人惊讶,因为 datetime.datetime() 返回一个日期时间对象djangoproject.com/documentation/0.96/models/basic 检查模型定义和示例:pub_date = models.DateTimeField() pub_date=datetime(2005, 7, 30)
  • "我知道它是可选的,问题是我的 datetimefield 设置了时间,它不是 00:00" 哦,现在我明白了。是的,没有时间参数,它设置为 00,所以它不返回 :)
【解决方案3】:

这是我使用 ipython 的 timeit 函数得到的结果:

from datetime import date
today = date.today()

timeit[Model.objects.filter(date_created__year=today.year, date_created__month=today.month, date_created__day=today.day)]
1000 loops, best of 3: 652 us per loop

timeit[Model.objects.filter(date_created__gte=today)]
1000 loops, best of 3: 631 us per loop

timeit[Model.objects.filter(date_created__startswith=today)]
1000 loops, best of 3: 541 us per loop

timeit[Model.objects.filter(date_created__contains=today)]
1000 loops, best of 3: 536 us per loop

包含似乎更快。

【讨论】:

  • 这个解决方案似乎是最新的。我很惊讶它得到了 4 个赞成票,因为当我尝试 contains 解决方案时,我收到错误消息:Unable to get repr for <class 'django.db.models.query.QuerySet'>
  • 我今天重新检查并更新了结果,我认为您的错误不是由__contains 过滤器引起的。但是,如果您遇到问题,您应该尝试使用 __gtedjango docs example
  • __contains 方法对我来说很好用。我认为这可能是最好的答案,因为它提供了性能比较。我投了不止一个,但我很惊讶它没有更多的支持。
【解决方案4】:

现在 Django 有__date queryset 过滤器,可以根据开发版本中的日期查询日期时间对象。因此,它将很快在 1.9 中可用。

【讨论】:

  • 是的,它是在 1.9 中添加的 docs.djangoproject.com/en/1.9/ref/models/querysets/#date
  • 最佳答案,适用于较新的 Django 版本
  • 这对我不起作用,不知道为什么:(我在 django 1.11 我的确切例外是:NotImplementedError: baseddatabaseoperations 的子类可能需要 datetime_cast_date() 方法
  • @AbdurRehmanKhan 是的,我目前面临同样的问题,使用 mongodb 你找到任何有用的解决方案了吗?
【解决方案5】:
Mymodel.objects.filter(date_time_field__contains=datetime.date(1986, 7, 28))

以上是我用过的。它不仅有效,而且还有一些内在的逻辑支持。

【讨论】:

  • 比这里的所有其他答案都好,谢谢!
【解决方案6】:

从 Django 1.9 开始,执行此操作的方法是在日期时间对象上使用 __date

例如: MyObject.objects.filter(datetime_attr__date=datetime.date(2009,8,22))

【讨论】:

  • 我读了几个关于 '__date' 的答案,但我发现它们都很复杂,直到我读到你的答案。它简单明了。
【解决方案7】:

这会产生与使用 __year、__month 和 __day 相同的结果,并且似乎对我有用:

YourModel.objects.filter(your_datetime_field__startswith=datetime.date(2009,8,22))

【讨论】:

  • 看起来像这样将日期对象转换为字符串并进行日期字符串比较,因此强制 db 进行全表扫描。对于大桌子,这会影响您的表现
【解决方案8】:

假设 active_on 是一个日期对象,将它增加 1 天然后做范围

next_day = active_on + datetime.timedelta(1)
queryset = queryset.filter(date_created__range=(active_on, next_day) )

【讨论】:

    【解决方案9】:

    你可以这样做

    MyObject.objects.filter(datetime_field__date=datetime.date(2009,8,22))
    

    或者如果您想在 2 个日期之间进行过滤

    MyObject.objects.filter(
        datetime_field__date__range=(datetime.date(2009,8,22), datetime.date(2009,9,22))
    )
    

    【讨论】:

      【解决方案10】:

      这里有一篇很棒的博文:Comparing Dates and Datetimes in the Django ORM

      为 Django>1.7,

      from django.db import models
      
      class MySQLDatetimeDate(models.Transform):
          """
          This implements a custom SQL lookup when using `__date` with datetimes.
          To enable filtering on datetimes that fall on a given date, import
          this transform and register it with the DateTimeField.
          """
          lookup_name = 'date'
      
          def as_sql(self, compiler, connection):
              lhs, params = compiler.compile(self.lhs)
              return 'DATE({})'.format(lhs), params
      
          @property
          def output_field(self):
              return models.DateField()
      

      然后你可以像这样在你的过滤器中使用它:

      Foo.objects.filter(created_on__date=date)
      

      编辑

      此解决方案绝对依赖于后端。来自文章:

      当然,此实现依赖于您的具有 DATE() 函数的特定 SQL 风格。 MySQL 可以。 SQLite 也是如此。另一方面,我个人没有使用过 PostgreSQL,但是一些谷歌搜索让我相信它没有 DATE() 函数。因此,如此简单的实现似乎必然在某种程度上依赖于后端。

      【讨论】:

      • 这是 MySQL 特有的吗?想知道类名的选择。
      • @BinojDavid 是的,它依赖于后端
      • 我使用 Django 1.8 和 PostgreSQL 9.6.6 对其进行了测试,它运行良好。实际上使用 PostgreSQL 你也可以使用这个语法:return '{}::date'.format(lhs), params
      【解决方案11】:

      这是一个有趣的技术——我利用了在 MySQL 上用 Django 实现的 startswith 过程来实现仅通过日期查找日期时间的结果。基本上,当 Django 在数据库中进行查找时,它必须对 DATETIME MySQL 存储对象进行字符串转换,因此您可以对其进行过滤,省略日期的时间戳部分——这样 %LIKE% 仅匹配日期对象,您将获得给定日期的每个时间戳。

      datetime_filter = datetime(2009, 8, 22) 
      MyObject.objects.filter(datetime_attr__startswith=datetime_filter.date())
      

      这将执行以下查询:

      SELECT (values) FROM myapp_my_object \ 
      WHERE myapp_my_object.datetime_attr LIKE BINARY 2009-08-22%
      

      在这种情况下,LIKE BINARY 将匹配日期的所有内容,无论时间戳如何。包括以下值:

      +---------------------+
      | datetime_attr       |
      +---------------------+
      | 2009-08-22 11:05:08 |
      +---------------------+
      

      希望这对每个人都有帮助,直到 Django 提出解决方案!

      【讨论】:

      • 好的,所以这似乎与上面的 mhost 和kethell 答案相同,但更多地描述了后端发生的事情。至少你有理由使用 contains 或 startswith 以及 datetime 的 date() 属性!
      【解决方案12】:

      嗯.. 我的解决方案有效:

      Mymodel.objects.filter(date_time_field__startswith=datetime.datetime(1986, 7, 28))
      

      【讨论】:

        【解决方案13】:
        Model.objects.filter(datetime__year=2011, datetime__month=2, datetime__day=30)
        

        【讨论】:

          【解决方案14】:

          在 Django 1.7.6 中工作:

          MyObject.objects.filter(datetime_attr__startswith=datetime.date(2009,8,22))
          

          【讨论】:

          • 这仅适用于您正在寻找确切日期的情况,例如,您不能使用__lte
          【解决方案15】:

          见文章Django Documentation

          ur_data_model.objects.filter(ur_date_field__gte=datetime(2009, 8, 22), ur_date_field__lt=datetime(2009, 8, 23))
          

          【讨论】:

          • 在 django 文档中它可以工作,因为 datetimefiled 的时间为 00:00
          【解决方案16】:
          person = Profile.objects.get(id=1)
          
          tasks = Task.objects.filter(assigned_to=person, time_stamp__year=person.time_stamp.utcnow().year)
          

          我所有的模型都有 time_stamp,所以我使用 person 对象来获取当前年份

          【讨论】:

            【解决方案17】:

            您可以在某些日期范围之间进行过滤

            2016-01-01 00:00:00 <--> 2016-04-01 23:59:59.99999

            User.objects.filter(date_joined__gte=datetime.combine(datetime.strptime('2016- 
            01-01', '%Y-%d-%m'), datetime.min.time()), 
            date_joined__lte=datetime.combine(datetime.strptime('2016-04-01', '%Y-%d-%m'), 
            datetime.max.time())).count()
            

            2016-01-01 00:00:00 <--> 2016-01-14 00:00:00

            User.objects.filter(date_joined__gte='2016-01-01', date_joined__lte='2016-1-14').count()
            

            【讨论】:

              【解决方案18】:

              您可以按日期过滤,因为日期格式与您的 django 日期格式相同。默认格式为 ISO YYYY-MM-DD

              target_date = "2009-08-22"
              qs = MyObject.objects.filter(datetime_attr__date=target_date)
              

              【讨论】:

                【解决方案19】:

                就像你有一个日期时间字段一样简单,你可以使用 datetime.date.today()

                context['now'] = Mymodel.objects.filter(date_time_field=datetime.date.today())
                

                【讨论】:

                  猜你喜欢
                  • 2020-09-08
                  • 2014-06-07
                  • 1970-01-01
                  • 2014-06-17
                  • 2021-01-27
                  • 2016-09-02
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多