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

150

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

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

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

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

Теги:
django-models

5 ответов

245
Лучший ответ

Используйте

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 (больше или меньше -than).

  • 0
    Каков тип данных date1? У меня есть объект datetime.
  • 1
    да тоже работает с datetime
Показать ещё 5 комментариев
118

Вы можете использовать django filter с datetime.date objects:

import datetime
samples = Sample.objects.filter(sampledate__gte=datetime.date(2011, 1, 1),
                                sampledate__lte=datetime.date(2011, 1, 31))
  • 0
    чтобы получить все, включая день 1 и 31, мы должны будем использовать gte так?
  • 2
    Да, используйте gte (> =).
Показать ещё 1 комментарий
58

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

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

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

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

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

  • 4
    Я думаю, что важно отметить, как импортировать объект date : >>> from datetime import date >>> startdate = date.today()
15

Вы можете обойти "несоответствие импеданса", вызванное отсутствием точности в сравнении с объектом DateTimeField/date, которое может возникнуть при использовании диапазона - с использованием datetime. timedelta​​strong > , чтобы добавить день к последней дате в диапазоне. Это работает как:

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. См. Дальнейшее объяснение в комментариях ниже.

  • 1
    Есть замечательная библиотека Делора, которая упрощает это с помощью метода усечения: delorean.readthedocs.org/en/latest/quickstart.html#truncation
  • 0
    @tojjer: выглядит многообещающе, но как здесь использовать метод усечения?
Показать ещё 6 комментариев
0

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

YourModel.objects.filter(date__date=timezone.now())
  • 2
    Это сработало и для меня, для новичков для ясности: (date__date = ...) означает ({whatColumnTheDateIsCalled} __ date)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню