it-swarm.com.ru

Запрос к базе данных Django: Как фильтровать объекты по диапазону дат?

У меня есть поле в одной модели, как

class Sample(models.Model):
    date = fields.DateField(auto_now=False)

Теперь мне нужно отфильтровать объекты по диапазону данных, например, по всем объектам с датой с 1 января 2011 по 31 января 2011?

Спасибо за вашу помощь!

181
user469652

Использование 

Sample.objects.filter(date__range=["2011-01-01", "2011-01-31"])

Или, если вы просто пытаетесь фильтровать по месяцам: 

Sample.objects.filter(date__year='2011', 
                      date__month='01')

Правка

Как сказал Бернхард Валлант, если вам нужен набор запросов, исключающий specified range ends, вы должны рассмотреть его решение , которое использует gt/lt (больше/меньше, чем).

325
crodjer

Вы можете использовать объекты Django filter with datetime.date :

import datetime
samples = Sample.objects.filter(sampledate__gte=datetime.date(2011, 1, 1),
                                sampledate__lte=datetime.date(2011, 1, 31))
153
Bernhard Vallant

При выполнении диапазонов Django с фильтром убедитесь, что вы знаете разницу между использованием объекта date и объекта datetime. __range включает даты, но если вы используете объект datetime для даты окончания, он не будет включать записи для этого дня, если время не установлено.

    startdate = date.today()
    enddate = startdate + timedelta(days=6)
    Sample.objects.filter(date__range=[startdate, enddate])

возвращает все записи от начала до конца, включая записи в эти даты. Плохой пример, так как это возвращает записи через неделю в будущее, но вы получаете дрейф.

    startdate = datetime.today()
    enddate = startdate + timedelta(days=6)
    Sample.objects.filter(date__range=[startdate, enddate])

будут отсутствовать записи за 24 часа в зависимости от того, какое время для полей даты установлено.

71
cademan

Вы можете обойти «несоответствие импеданса», вызванное отсутствием точности в сравнении объектов DateTimeField/date, которое может возникнуть при использовании range - с помощью datetime.timedelta для добавления дня к последнему дню дата в диапазоне. Это работает как:

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])

Как уже говорилось ранее, не делая ничего подобного, записи игнорируются в последний день.

Отредактировано, чтобы избежать использования datetime.combine - кажется более логичным придерживаться экземпляров даты при сравнении с DateTimeField, а не возиться с одноразовыми (и запутывающими) объектами datetime. Дальнейшее объяснение в комментариях ниже.

16
trojjer

Это просто,  

YourModel.objects.filter(YOUR_DATE_FIELD__date=timezone.now())

Работает для меня

5
Jonhatan Fajardo

По-прежнему актуально сегодня . Вы также можете сделать:

import dateutil
import pytz

date = dateutil.parser.parse('02/11/2019').replace(tzinfo=pytz.UTC)
0
Bhavik Shah