Browse Source

Fixed #24170 -- Implemented decompress for BaseRangeField widgets

Ng Zhi An 10 năm trước cách đây
mục cha
commit
4669b6a807

+ 13 - 2
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)

+ 25 - 1
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.

+ 21 - 0
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', ''),
+            '<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" />'
+        )