#31872: Postgres DecimalRangeField ignores bounds
--------------------------------------------+------------------------
Reporter: Jack Delany | Owner: (none)
Type: Uncategorized | Status: new
Component: contrib.postgres | Version: 3.1
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
--------------------------------------------+------------------------
Found in 2.2, still in master.
I believe there is an issue in the internal conversion/prep routine for
Range types.
{{{
from django.contrib.postgres.fields.ranges import DecimalRangeField
class OneModel(models.Model):
val = DecimalRangeField()
}}}
Given a simple object created from a tuple:
{{{
x = OneModel(val=(1.0, 2.0, "[]"))
x.save()
}}}
This emits the following SQL with an incorrect bounds:
{{{
INSERT INTO "app_onemodel" ("val") VALUES ('[1.0,2.0)') ...
}}}
Alternately:
{{{
from psycopg2.extras import NumericRange
x = OneModel(val=NumericRange(1.0, 2.0, "[]"))
x.save()
}}}
This one does what I expect and emits the following SQL and preserves the
bounds:
{{{
INSERT INTO "app_onemodel" ("val") VALUES ('[1.0,2.0]') ...
}}}
I tracked it down to:
{{{
django/contrib/postgres/fields/ranges.py:74:
def get_prep_value(self, value):
if value is None:
return None
elif isinstance(value, Range):
return value
elif isinstance(value, (list, tuple)):
# Problem is here
>>>> return self.range_type(value[0], value[1])
# Better: return self.range_type(*value)
return value
}}}
Given that get_prep_value() is calling through to the underlying psycopg2
object, I'd presume the intention is that the behavior matches the
underlying psycopg2 semantics.
Same pattern is found at line 86 in the ```RangeField.to_python()```
method.
I realize that by using (*value) it'll change the behavior if someone has
been passing tuples/list with more than three items, but the behavior
seems wrong in that case to silently ignore the extra items. One could be
more explicit and handle the two-item and three-item tuple/list cases
individually. That would minimize the changes.
There is another case #27147 that is related. In my experience, Ranges
generally work correctly and they do have the underlying Postgres behavior
(eg bounds normalizing for discreet ranges) so I'm not completely clear
what the issue is that #27147 is trying to address.
--
Ticket URL: <https://code.djangoproject.com/ticket/31872>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/051.a047f4b08530349c79b353c3dad499ad%40djangoproject.com.