Фильтруйте поле диапазона Django, сравнивая его с точкой, а не с другим диапазоном

В документах, относящихся к конкретным полям модели PostgreSQL, очень подробно описывается, как сравнивать один RangeField диапазон с другим. Но как вы сравниваете диапазон с одной точкой?

Например, если у меня есть модель с valid_range=DateTimeRangeField и я хочу найти все экземпляры, которые больше недействительны, мне нужно сделать что-то вроде:

from django.utils import timezone as tz

MyProduct.objects.filter(valid_range__lt=tz.now())

Но это запрещено. Я думал, что мог бы использовать fully_lt, но это тоже запрещено для конкретной даты.

Как мне отфильтровать DateTimeRangeField, чтобы найти экземпляры, диапазоны которых заканчивались до определенной даты-времени?

Ответ вроде как дан в документации, но он очень тонкий:

заканчивается на

Возвращаемые объекты имеют заданную верхнюю границу. Может быть привязан к действительным запросам для базового поля.

Другими словами, endswith может выступать в качестве псевдонима для верхней границы диапазона.

Итак, эквивалент этого в Postgres-обработанном SQL:

WHERE upper(date_range) < '2050-01-01'

это:

.filter(date_range__ends_with__lt=datetime(2050, 1, 1))

Вы можете убедиться в этом, добавив .query в конец определения вашего набора запросов:

>>> print(MyProduct.objects.filter(valid_range__endswith__lt=(datetime(2050, 1, 1))).query)
...WHERE upper("myproduct"."valid_range") < 2050-01-01 00:00:00+00:00

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

Вернуться на верх