Commit 4669b6a8 authored by Ng Zhi An's avatar Ng Zhi An
Browse files

Fixed #24170 -- Implemented decompress for BaseRangeField widgets

parent 38c17871
Loading
Loading
Loading
Loading
+13 −2
Original line number Diff line number Diff line
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)
+25 −1
Original line number Diff line number Diff line
@@ -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.
+21 −0
Original line number Diff line number Diff line
@@ -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" />'
        )