Django, filter by specified month and year in date range

后端 未结 3 1965
没有蜡笔的小新
没有蜡笔的小新 2021-02-05 01:04

I have the following models

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

class Departure_Date(models.Model):         


        
相关标签:
3条回答
  • 2021-02-05 01:09

    You can get around the "impedance mismatch" caused by the lack of precision in the DateTimeField/date object comparison -- that can occur if using range -- by using a datetime.timedelta to add a day to last date in the range. This works like:

    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])
    
    0 讨论(0)
  • 2021-02-05 01:17

    Solution using python code only. Main idea is to construct date_from and date_to with python. Then these dates can be used in filter with __lte and __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))
    

    Now this will work:

    >>> 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>]
    
    0 讨论(0)
  • 2021-02-05 01:19

    Check the 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)
    

    Alternative method using .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])
    

    There is a specific case where above query does not yield a desired result.

    For example:

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

    Then %(month)s >= MONTH(date_from) condition is wrong because month 1 is < month 11 in date_from but year is different so MySQL IF condition is required here:

    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])
    
    0 讨论(0)
提交回复
热议问题