Как отфильтровать объекты запросов по диапазону дат в Django? - PullRequest
194 голосов
/ 12 января 2011

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

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

Теперь мне нужно отфильтровать объекты по диапазону дат.

Как отфильтровать все объекты, которыеиметь дату между 1-Jan-2011 и 31-Jan-2011?

Ответы [ 7 ]

339 голосов
/ 12 января 2011

Используйте

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

162 голосов
/ 12 января 2011

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

import datetime
samples = Sample.objects.filter(sampledate__gte=datetime.date(2011, 1, 1),
                                sampledate__lte=datetime.date(2011, 1, 31))
73 голосов
/ 01 июня 2011

При выполнении диапазонов 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 часа в зависимости от того, какое время для полей даты установлено.

17 голосов
/ 11 декабря 2012

Вы можете обойти "несоответствие импедансов", вызванное отсутствием точности в 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 объектами. Дальнейшее объяснение в комментариях ниже.

4 голосов
/ 22 сентября 2017

Прост,

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

У меня работает

0 голосов
/ 09 июля 2019

Чтобы сделать его более гибким, вы можете создать FilterBackend, как показано ниже:

class AnalyticsFilterBackend(generic_filters.BaseFilterBackend):
    def filter_queryset(self, request, queryset, view):
        predicate = request.query_params # or request.data for POST

        if predicate.get('from_date', None) is not None and predicate.get('to_date', None) is not None:
            queryset = queryset.filter(your_date__range=(predicate['from_date'], predicate['to_date']))

        if predicate.get('from_date', None) is not None and predicate.get('to_date', None) is None:
            queryset = queryset.filter(your_date__gte=predicate['from_date'])

        if predicate.get('to_date', None) is not None and predicate.get('from_date', None) is None:
            queryset = queryset.filter(your_date__lte=predicate['to_date'])
        return queryset
0 голосов
/ 14 февраля 2019

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

import dateutil
import pytz

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