Фильтруйте поле диапазона 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
Как всегда при работе с диапазонами, тщательно продумайте, включена ли конечная точка диапазона или исключена. (По умолчанию конечная точка исключена из диапазона.)