mirror of
				https://github.com/django/django.git
				synced 2025-10-30 17:16:10 +00:00 
			
		
		
		
	[3.0.x] Fixed #30758 -- Made RangeFields use multiple hidden inputs for initial data.
Backport of faf4b988fe from master.
			
			
This commit is contained in:
		
				
					committed by
					
						 Mariusz Felisiak
						Mariusz Felisiak
					
				
			
			
				
	
			
			
			
						parent
						
							14125bb039
						
					
				
				
					commit
					685d956764
				
			| @@ -4,21 +4,40 @@ from psycopg2.extras import DateRange, DateTimeTZRange, NumericRange | |||||||
|  |  | ||||||
| from django import forms | from django import forms | ||||||
| from django.core import exceptions | from django.core import exceptions | ||||||
| from django.forms.widgets import MultiWidget | from django.forms.widgets import HiddenInput, MultiWidget | ||||||
| from django.utils.deprecation import RemovedInDjango31Warning | from django.utils.deprecation import RemovedInDjango31Warning | ||||||
| from django.utils.translation import gettext_lazy as _ | from django.utils.translation import gettext_lazy as _ | ||||||
|  |  | ||||||
| __all__ = [ | __all__ = [ | ||||||
|     'BaseRangeField', 'IntegerRangeField', 'DecimalRangeField', |     'BaseRangeField', 'IntegerRangeField', 'DecimalRangeField', | ||||||
|     'DateTimeRangeField', 'DateRangeField', 'FloatRangeField', 'RangeWidget', |     'DateTimeRangeField', 'DateRangeField', 'FloatRangeField', | ||||||
|  |     'HiddenRangeWidget', 'RangeWidget', | ||||||
| ] | ] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class RangeWidget(MultiWidget): | ||||||
|  |     def __init__(self, base_widget, attrs=None): | ||||||
|  |         widgets = (base_widget, base_widget) | ||||||
|  |         super().__init__(widgets, attrs) | ||||||
|  |  | ||||||
|  |     def decompress(self, value): | ||||||
|  |         if value: | ||||||
|  |             return (value.lower, value.upper) | ||||||
|  |         return (None, None) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class HiddenRangeWidget(RangeWidget): | ||||||
|  |     """A widget that splits input into two <input type="hidden"> inputs.""" | ||||||
|  |     def __init__(self, attrs=None): | ||||||
|  |         super().__init__(HiddenInput, attrs) | ||||||
|  |  | ||||||
|  |  | ||||||
| class BaseRangeField(forms.MultiValueField): | class BaseRangeField(forms.MultiValueField): | ||||||
|     default_error_messages = { |     default_error_messages = { | ||||||
|         'invalid': _('Enter two valid values.'), |         'invalid': _('Enter two valid values.'), | ||||||
|         'bound_ordering': _('The start of the range must not exceed the end of the range.'), |         'bound_ordering': _('The start of the range must not exceed the end of the range.'), | ||||||
|     } |     } | ||||||
|  |     hidden_widget = HiddenRangeWidget | ||||||
|  |  | ||||||
|     def __init__(self, **kwargs): |     def __init__(self, **kwargs): | ||||||
|         if 'widget' not in kwargs: |         if 'widget' not in kwargs: | ||||||
| @@ -96,14 +115,3 @@ class DateRangeField(BaseRangeField): | |||||||
|     default_error_messages = {'invalid': _('Enter two valid dates.')} |     default_error_messages = {'invalid': _('Enter two valid dates.')} | ||||||
|     base_field = forms.DateField |     base_field = forms.DateField | ||||||
|     range_type = DateRange |     range_type = DateRange | ||||||
|  |  | ||||||
|  |  | ||||||
| class RangeWidget(MultiWidget): |  | ||||||
|     def __init__(self, base_widget, attrs=None): |  | ||||||
|         widgets = (base_widget, base_widget) |  | ||||||
|         super().__init__(widgets, attrs) |  | ||||||
|  |  | ||||||
|     def decompress(self, value): |  | ||||||
|         if value: |  | ||||||
|             return (value.lower, value.upper) |  | ||||||
|         return (None, None) |  | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ from decimal import Decimal | |||||||
| from django import forms | from django import forms | ||||||
| from django.core import exceptions, serializers | from django.core import exceptions, serializers | ||||||
| from django.db.models import DateField, DateTimeField, F, Func, Value | from django.db.models import DateField, DateTimeField, F, Func, Value | ||||||
|  | from django.http import QueryDict | ||||||
| from django.test import ignore_warnings, override_settings | from django.test import ignore_warnings, override_settings | ||||||
| from django.utils import timezone | from django.utils import timezone | ||||||
| from django.utils.deprecation import RemovedInDjango31Warning | from django.utils.deprecation import RemovedInDjango31Warning | ||||||
| @@ -512,6 +513,24 @@ class TestFormField(PostgreSQLSimpleTestCase): | |||||||
|         value = field.clean(['', '']) |         value = field.clean(['', '']) | ||||||
|         self.assertIsNone(value) |         self.assertIsNone(value) | ||||||
|  |  | ||||||
|  |     def test_datetime_form_initial_data(self): | ||||||
|  |         class DateTimeRangeForm(forms.Form): | ||||||
|  |             datetime_field = pg_forms.DateTimeRangeField(show_hidden_initial=True) | ||||||
|  |  | ||||||
|  |         data = QueryDict(mutable=True) | ||||||
|  |         data.update({ | ||||||
|  |             'datetime_field_0': '2010-01-01 11:13:00', | ||||||
|  |             'datetime_field_1': '', | ||||||
|  |             'initial-datetime_field_0': '2010-01-01 10:12:00', | ||||||
|  |             'initial-datetime_field_1': '', | ||||||
|  |         }) | ||||||
|  |         form = DateTimeRangeForm(data=data) | ||||||
|  |         self.assertTrue(form.has_changed()) | ||||||
|  |  | ||||||
|  |         data['initial-datetime_field_0'] = '2010-01-01 11:13:00' | ||||||
|  |         form = DateTimeRangeForm(data=data) | ||||||
|  |         self.assertFalse(form.has_changed()) | ||||||
|  |  | ||||||
|     def test_rendering(self): |     def test_rendering(self): | ||||||
|         class RangeForm(forms.Form): |         class RangeForm(forms.Form): | ||||||
|             ints = pg_forms.IntegerRangeField() |             ints = pg_forms.IntegerRangeField() | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user