Fixed #29916 -- Added lower_inc, lower_inf, upper_inc, and upper_inf lookups for RangeFields.
Co-Authored-By: Mariusz Felisiak <felisiak.mariusz@gmail.com>
This commit is contained in:
parent
efc3e32d6d
commit
24b9f50823
|
@ -284,3 +284,31 @@ class IsEmpty(models.Transform):
|
||||||
lookup_name = 'isempty'
|
lookup_name = 'isempty'
|
||||||
function = 'isempty'
|
function = 'isempty'
|
||||||
output_field = models.BooleanField()
|
output_field = models.BooleanField()
|
||||||
|
|
||||||
|
|
||||||
|
@RangeField.register_lookup
|
||||||
|
class LowerInclusive(models.Transform):
|
||||||
|
lookup_name = 'lower_inc'
|
||||||
|
function = 'LOWER_INC'
|
||||||
|
output_field = models.BooleanField()
|
||||||
|
|
||||||
|
|
||||||
|
@RangeField.register_lookup
|
||||||
|
class LowerInfinite(models.Transform):
|
||||||
|
lookup_name = 'lower_inf'
|
||||||
|
function = 'LOWER_INF'
|
||||||
|
output_field = models.BooleanField()
|
||||||
|
|
||||||
|
|
||||||
|
@RangeField.register_lookup
|
||||||
|
class UpperInclusive(models.Transform):
|
||||||
|
lookup_name = 'upper_inc'
|
||||||
|
function = 'UPPER_INC'
|
||||||
|
output_field = models.BooleanField()
|
||||||
|
|
||||||
|
|
||||||
|
@RangeField.register_lookup
|
||||||
|
class UpperInfinite(models.Transform):
|
||||||
|
lookup_name = 'upper_inf'
|
||||||
|
function = 'UPPER_INF'
|
||||||
|
output_field = models.BooleanField()
|
||||||
|
|
|
@ -864,6 +864,62 @@ Returned objects are empty ranges. Can be chained to valid lookups for a
|
||||||
>>> Event.objects.filter(ages__isempty=True)
|
>>> Event.objects.filter(ages__isempty=True)
|
||||||
<QuerySet []>
|
<QuerySet []>
|
||||||
|
|
||||||
|
.. fieldlookup:: rangefield.lower_inc
|
||||||
|
|
||||||
|
``lower_inc``
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
.. versionadded:: 3.1
|
||||||
|
|
||||||
|
Returns objects that have inclusive or exclusive lower bounds, depending on the
|
||||||
|
boolean value passed. Can be chained to valid lookups for a
|
||||||
|
:class:`~django.db.models.BooleanField`.
|
||||||
|
|
||||||
|
>>> Event.objects.filter(ages__lower_inc=True)
|
||||||
|
<QuerySet [<Event: Soft play>, <Event: Pub trip>]>
|
||||||
|
|
||||||
|
.. fieldlookup:: rangefield.lower_inf
|
||||||
|
|
||||||
|
``lower_inf``
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
.. versionadded:: 3.1
|
||||||
|
|
||||||
|
Returns objects that have unbounded (infinite) or bounded lower bound,
|
||||||
|
depending on the boolean value passed. Can be chained to valid lookups for a
|
||||||
|
:class:`~django.db.models.BooleanField`.
|
||||||
|
|
||||||
|
>>> Event.objects.filter(ages__lower_inf=True)
|
||||||
|
<QuerySet []>
|
||||||
|
|
||||||
|
.. fieldlookup:: rangefield.upper_inc
|
||||||
|
|
||||||
|
``upper_inc``
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
.. versionadded:: 3.1
|
||||||
|
|
||||||
|
Returns objects that have inclusive or exclusive upper bounds, depending on the
|
||||||
|
boolean value passed. Can be chained to valid lookups for a
|
||||||
|
:class:`~django.db.models.BooleanField`.
|
||||||
|
|
||||||
|
>>> Event.objects.filter(ages__upper_inc=True)
|
||||||
|
<QuerySet []>
|
||||||
|
|
||||||
|
.. fieldlookup:: rangefield.upper_inf
|
||||||
|
|
||||||
|
``upper_inf``
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
.. versionadded:: 3.1
|
||||||
|
|
||||||
|
Returns objects that have unbounded (infinite) or bounded upper bound,
|
||||||
|
depending on the boolean value passed. Can be chained to valid lookups for a
|
||||||
|
:class:`~django.db.models.BooleanField`.
|
||||||
|
|
||||||
|
>>> Event.objects.filter(ages__upper_inf=True)
|
||||||
|
<QuerySet [<Event: Pub trip>]>
|
||||||
|
|
||||||
Defining your own range types
|
Defining your own range types
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,10 @@ Minor features
|
||||||
:class:`~django.contrib.postgres.fields.ArrayField` and
|
:class:`~django.contrib.postgres.fields.ArrayField` and
|
||||||
:class:`~django.contrib.postgres.fields.RangeField`.
|
:class:`~django.contrib.postgres.fields.RangeField`.
|
||||||
|
|
||||||
|
* The new :lookup:`rangefield.lower_inc`, :lookup:`rangefield.lower_inf`,
|
||||||
|
:lookup:`rangefield.upper_inc`, and :lookup:`rangefield.upper_inf` allows
|
||||||
|
querying :class:`~django.contrib.postgres.fields.RangeField` by a bound type.
|
||||||
|
|
||||||
:mod:`django.contrib.redirects`
|
:mod:`django.contrib.redirects`
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -296,6 +296,30 @@ class TestQuerying(PostgreSQLTestCase):
|
||||||
[self.objs[0], self.objs[1]],
|
[self.objs[0], self.objs[1]],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_bound_type(self):
|
||||||
|
decimals = RangesModel.objects.bulk_create([
|
||||||
|
RangesModel(decimals=NumericRange(None, 10)),
|
||||||
|
RangesModel(decimals=NumericRange(10, None)),
|
||||||
|
RangesModel(decimals=NumericRange(5, 15)),
|
||||||
|
RangesModel(decimals=NumericRange(5, 15, '(]')),
|
||||||
|
])
|
||||||
|
tests = [
|
||||||
|
('lower_inc', True, [decimals[1], decimals[2]]),
|
||||||
|
('lower_inc', False, [decimals[0], decimals[3]]),
|
||||||
|
('lower_inf', True, [decimals[0]]),
|
||||||
|
('lower_inf', False, [decimals[1], decimals[2], decimals[3]]),
|
||||||
|
('upper_inc', True, [decimals[3]]),
|
||||||
|
('upper_inc', False, [decimals[0], decimals[1], decimals[2]]),
|
||||||
|
('upper_inf', True, [decimals[1]]),
|
||||||
|
('upper_inf', False, [decimals[0], decimals[2], decimals[3]]),
|
||||||
|
]
|
||||||
|
for lookup, filter_arg, excepted_result in tests:
|
||||||
|
with self.subTest(lookup=lookup, filter_arg=filter_arg):
|
||||||
|
self.assertSequenceEqual(
|
||||||
|
RangesModel.objects.filter(**{'decimals__%s' % lookup: filter_arg}),
|
||||||
|
excepted_result,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestQueryingWithRanges(PostgreSQLTestCase):
|
class TestQueryingWithRanges(PostgreSQLTestCase):
|
||||||
def test_date_range(self):
|
def test_date_range(self):
|
||||||
|
|
Loading…
Reference in New Issue