From 4669b6a807811d6763b9fdc5df974cb67aa1fb56 Mon Sep 17 00:00:00 2001 From: Ng Zhi An Date: Sun, 18 Jan 2015 02:20:42 +0000 Subject: [PATCH] Fixed #24170 -- Implemented decompress for BaseRangeField widgets --- django/contrib/postgres/forms/ranges.py | 15 ++++++++++++-- docs/ref/contrib/postgres/forms.txt | 26 ++++++++++++++++++++++++- tests/postgres_tests/test_ranges.py | 21 ++++++++++++++++++++ 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/django/contrib/postgres/forms/ranges.py b/django/contrib/postgres/forms/ranges.py index 4f8989a96d..23db4fe514 100644 --- a/django/contrib/postgres/forms/ranges.py +++ b/django/contrib/postgres/forms/ranges.py @@ -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) diff --git a/docs/ref/contrib/postgres/forms.txt b/docs/ref/contrib/postgres/forms.txt index f6226c4b55..405a005f03 100644 --- a/docs/ref/contrib/postgres/forms.txt +++ b/docs/ref/contrib/postgres/forms.txt @@ -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. diff --git a/tests/postgres_tests/test_ranges.py b/tests/postgres_tests/test_ranges.py index 6d35e62cc5..bc15987ba7 100644 --- a/tests/postgres_tests/test_ranges.py +++ b/tests/postgres_tests/test_ranges.py @@ -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', ''), + '' + ) + self.assertHTMLEqual( + f.widget.render('datetimerange', None), + '' + ) + 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), + '' + )