【问题标题】:Django, filter by specified month and year in date rangeDjango,按日期范围内的指定月份和年份过滤
【发布时间】:2012-12-14 04:59:43
【问题描述】:

我有以下型号

class Destination_Deal(models.Model):
    name = models.CharField(_("Nombre"),max_length=200)

class Departure_Date(models.Model):
    date_from= models.DateField(_('Desde'))    
    date_to= models.DateField(_('Hasta'))
    destination_deal = models.ForeignKey(Destination_Deal,verbose_name = _("Oferta de Destino"))

这是department_date表中的实际数据

id  date_from   date_to     destination_deal_id
1   2012-11-01  2013-03-17  1
2   2012-11-01  2012-12-16  2
3   2012-09-16  2012-10-31  3
4   2012-11-01  2012-12-16  3
5   2013-01-04  2013-01-11  4

如果指定的月份和年份在 date_from 和 date_to 之间,我想过滤 Destination_Deals。

示例 1

月份:9 月 (09)
年份:2012

想要的出发日期结果:
ID 3:它是唯一触及 09/2012 的数据范围

示例 2

月份:二月 (02)
年份:2013

想要的出发日期结果:
ID 1:02/2012 早于 03/2012

所以,日子其实是无所谓的。如果月份和年份在 date_from 和 date_to 之间,即使相差一天也必须过滤。

我想我必须使用this 之类的东西,但我不知道该怎么做。

提前致谢! 米格尔

---编辑---
这是对 Aamir Adnan 答案的测试,但它没有像我预期的那样工作,因为 ID 1 也必须返回,因为它从 2012 年 11 月到 2013 年 3 月,所以介于 2013 年 1 月之间。

Departure_Date.objects.all()
[<Departure_Date: id: 1 - from: 2012-11-01 - to: 2013-03-17>,
<Departure_Date: id: 2 - from: 2012-11-01 - to: 2012-12-16>,
<Departure_Date: id: 3 - from: 2012-09-16 - to: 2012-10-31>,
<Departure_Date: id: 4 - from: 2012-11-01 - to: 2012-12-16>,
<Departure_Date: id: 5 - from: 2013-01-04 - to: 2013-01-11>]


month:1
year:2013
where = '%(year)s >= YEAR(date_from) AND %(month)s >= MONTH(date_from) \
    AND %(year)s <= YEAR(date_to) AND %(month)s <= MONTH(date_to)' % \
    {'year': year, 'month': month}
Departure_Date.objects.extra(where=[where])
[<Departure_Date: id: 5 - from: 2013-01-04 - to: 2013-01-11>]

【问题讨论】:

    标签: python django


    【解决方案1】:

    您可以使用__gte__lte 的2 个过滤器:

    import datetime as dt
    
    start = dt.date(2012, 12, 11)
    end = dt.date(2012, 12, 18)
    ExampleModel.objects.filter(date_field__gte=start).filter(date_field__lte=end)
    

    【讨论】:

      【解决方案2】:

      您可以通过使用 datetime 来解决由于 DateTimeField/date 对象比较中缺乏精确性而导致的“阻抗不匹配”——如果使用 range 可能会出现这种情况。 timedelta 将日期添加到范围内的最后一个日期。这就像:

      import datetime
      
      start = date(2012, 12, 11)
      end = date(2012, 12, 18)
      new_end = end + datetime.timedelta(days=1)
      
      ExampleModel.objects.filter(some_datetime_field__range=[start, new_end])
      

      【讨论】:

        【解决方案3】:

        仅使用 python 代码的解决方案。主要思想是用python构造date_from和date_to。那么这些日期可以在filter__lte__gte 中使用:

        import calendar
        from datetime import datetime
        from django.db.models import Q
        
        def in_month_year(month, year):
            d_fmt = "{0:>02}.{1:>02}.{2}"
            date_from = datetime.strptime(
                d_fmt.format(1, month, year), '%d.%m.%Y').date()
            last_day_of_month = calendar.monthrange(year, month)[1]
            date_to = datetime.strptime(
                d_fmt.format(last_day_of_month, month, year), '%d.%m.%Y').date()
            return Departure_Date.objects.filter(
                Q(date_from__gte=date_from, date_from__lte=date_to)
                 |
                Q(date_from__lt=date_from, date_to__gte=date_from))
        

        现在这将起作用:

        >>> Departure_Date.objects.all()
        [<Departure_Date: id: 1 - from: 2012-11-01 - to: 2013-03-17>,
        <Departure_Date: id: 2 - from: 2012-11-01 - to: 2012-12-16>,
        <Departure_Date: id: 3 - from: 2012-09-16 - to: 2012-10-31>,
        <Departure_Date: id: 4 - from: 2012-11-01 - to: 2012-12-16>,
        <Departure_Date: id: 5 - from: 2013-01-04 - to: 2013-01-11>]
        
        
        >>> in_month_year(month=1, year=2013)
        [<Departure_Date: id: 1 - from: 2012-11-01 - to: 2013-03-17>,
        <Departure_Date: id: 5 - from: 2013-01-04 - to: 2013-01-11>]
        

        【讨论】:

          【解决方案4】:

          查看documentation

          year = 2012
          month = 09
          Departure_Date.objects.filter(date_from__year__gte=year,
                                        date_from__month__gte=month,
                                        date_to__year__lte=year,
                                        date_to__month__lte=month)
          

          使用.extra的替代方法:

          where = '%(year)s >= YEAR(date_from) AND %(month)s >= MONTH(date_from) \
                  AND %(year)s <= YEAR(date_to) AND %(month)s <= MONTH(date_to)' % \
                  {'year': year, 'month': month}
          Departure_Date.objects.extra(where=[where])
          

          在特定情况下,上述查询不会产生所需的结果。

          例如:

          date_from='2012-11-01'
          date_to='2013-03-17'
          and input is
          year=2013
          month=1
          

          那么%(month)s &gt;= MONTH(date_from) 条件是错误的,因为在date_from 中第1 个月是IF 条件:

          where = '%(year)s >= YEAR(date_from) AND IF(%(year)s > YEAR(date_from), \
               IF(%(month)s > MONTH(date_from), %(month)s >= MONTH(date_from), %(month)s < MONTH(date_from)), \
               IF(%(month)s < MONTH(date_from), %(month)s < MONTH(date_from), %(month)s >= MONTH(date_from))) \
               AND %(year)s <= YEAR(date_to) \
               AND %(month)s <= MONTH(date_to)' % \
               {'year': year, 'month': month}
          Departure_Date.objects.extra(where=[where])
          

          【讨论】:

          • 我收到以下错误:“FieldError: Join on field 'date_to' not allowed. 你拼错了查找类型的'month'吗?” AFAIK 不能混合后缀还是我错了?
          • 这很奇怪,我知道在日期扩展查找(例如年、月)__in 是不允许的。请检查我的答案中的替代方法。谢谢
          • 现在我得到 "DatabaseError: (1064, "您的 SQL 语法有错误;请查看与您的 MySQL 服务器版本相对应的手册,了解在 'MONTH(date_from) 附近使用的正确语法 > = 12 YEAR(date_to)
          • 谢谢。我已经尝试过使用“and”,但这不是我所要求的。您是否尝试过使用示例数据?另一个例子,月:1 - 年:2013。结果必须是 ID 1 和 ID 5。如果可能的话,我想避免使用额外的。
          • 请再次测试,如果它没有按照您的要求进行,请告诉我。我已经更新了查询,并在您的数据上对其进行了测试,并且运行良好。请复制我再次发布的查询。
          猜你喜欢
          • 2021-11-01
          • 2012-08-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-23
          • 1970-01-01
          • 2019-01-07
          • 2021-04-16
          相关资源
          最近更新 更多