Fixed #24170 -- Implemented decompress for BaseRangeField widgets

This commit is contained in:
Ng Zhi An 2015-01-18 02:20:42 +00:00
parent 38c17871bb
commit 4669b6a807
3 changed files with 59 additions and 3 deletions

View File

@ -1,5 +1,6 @@
from django.core import exceptions
from django import forms
from django.forms.widgets import MultiWidget
from django.utils.translation import ugettext_lazy as _
from psycopg2.extras import NumericRange, DateRange, DateTimeTZRange
@ -15,8 +16,7 @@ class BaseRangeField(forms.MultiValueField):
}
def __init__(self, **kwargs):
widget = forms.MultiWidget([self.base_field.widget, self.base_field.widget])
kwargs.setdefault('widget', widget)
kwargs.setdefault('widget', RangeWidget(self.base_field.widget))
kwargs.setdefault('fields', [self.base_field(required=False), self.base_field(required=False)])
kwargs.setdefault('required', False)
kwargs.setdefault('require_all_fields', False)
@ -67,3 +67,14 @@ class DateTimeRangeField(BaseRangeField):
class DateRangeField(BaseRangeField):
base_field = forms.DateField
range_type = DateRange
class RangeWidget(MultiWidget):
def __init__(self, base_widget, attrs=None):
widgets = (base_widget, base_widget)
super(RangeWidget, self).__init__(widgets, attrs)
def decompress(self, value):
if value:
return (value.lower, value.upper)
return (None, None)

View File

@ -161,7 +161,8 @@ Range Fields
This group of fields all share similar functionality for accepting range data.
They are based on :class:`~django.forms.MultiValueField`. They treat one
omitted value as an unbounded range. They also validate that the lower bound is
not greater than the upper bound.
not greater than the upper bound. All of these fields use
:class:`~django.contrib.postgres.fields.RangeWidget`.
IntegerRangeField
~~~~~~~~~~~~~~~~~
@ -199,3 +200,26 @@ DateRangeField
Based on :class:`~django.forms.DateField` and translates its input into
:class:`~psycopg2:psycopg2.extras.DateRange`. Default for
:class:`~django.contrib.postgres.fields.DateRangeField`.
Widgets
-------
RangeWidget
~~~~~~~~~~~
.. class:: RangeWidget(base_widget, attrs=None)
Widget used by all of the range fields.
Based on :class:`~django.forms.MultiWidget`.
:class:`~RangeWidget` has one required argument:
.. attribute:: base_widget
A :class:`~RangeWidget` comprises a 2-tuple of ``base_widget``.
.. method:: decompress(value)
Takes a single "compressed" value of a field, for example a
:class:`~django.contrib.postgres.fields.DateRangeField`,
and returns a tuple representing and lower and upper bound.

View File

@ -374,3 +374,24 @@ class TestFormField(TestCase):
model_field = pg_fields.DateTimeRangeField()
form_field = model_field.formfield()
self.assertIsInstance(form_field, pg_forms.DateTimeRangeField)
class TestWidget(TestCase):
def test_range_widget(self):
f = pg_forms.ranges.DateTimeRangeField()
self.assertHTMLEqual(
f.widget.render('datetimerange', ''),
'<input type="text" name="datetimerange_0" /><input type="text" name="datetimerange_1" />'
)
self.assertHTMLEqual(
f.widget.render('datetimerange', None),
'<input type="text" name="datetimerange_0" /><input type="text" name="datetimerange_1" />'
)
dt_range = DateTimeTZRange(
datetime.datetime(2006, 1, 10, 7, 30),
datetime.datetime(2006, 2, 12, 9, 50)
)
self.assertHTMLEqual(
f.widget.render('datetimerange', dt_range),
'<input type="text" name="datetimerange_0" value="2006-01-10 07:30:00" /><input type="text" name="datetimerange_1" value="2006-02-12 09:50:00" />'
)