Loading django/forms/fields.py +34 −11 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ from django.core import validators from django.core.exceptions import ValidationError from django.forms.util import ErrorList, from_current_timezone, to_current_timezone from django.forms.widgets import ( TextInput, PasswordInput, EmailInput, URLInput, HiddenInput, TextInput, NumberInput, EmailInput, URLInput, HiddenInput, MultipleHiddenInput, ClearableFileInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple, DateInput, DateTimeInput, TimeInput, SplitDateTimeWidget, SplitHiddenDateTimeWidget, FILE_INPUT_CONTRADICTION Loading Loading @@ -234,6 +234,7 @@ class IntegerField(Field): def __init__(self, max_value=None, min_value=None, *args, **kwargs): self.max_value, self.min_value = max_value, min_value kwargs.setdefault('widget', NumberInput if not kwargs.get('localize') else self.widget) super(IntegerField, self).__init__(*args, **kwargs) if max_value is not None: Loading @@ -257,6 +258,16 @@ class IntegerField(Field): raise ValidationError(self.error_messages['invalid']) return value def widget_attrs(self, widget): attrs = super(IntegerField, self).widget_attrs(widget) if isinstance(widget, NumberInput): if self.min_value is not None: attrs['min'] = self.min_value if self.max_value is not None: attrs['max'] = self.max_value return attrs class FloatField(IntegerField): default_error_messages = { 'invalid': _('Enter a number.'), Loading @@ -278,25 +289,24 @@ class FloatField(IntegerField): raise ValidationError(self.error_messages['invalid']) return value class DecimalField(Field): def widget_attrs(self, widget): attrs = super(FloatField, self).widget_attrs(widget) if isinstance(widget, NumberInput): attrs.setdefault('step', 'any') return attrs class DecimalField(IntegerField): default_error_messages = { 'invalid': _('Enter a number.'), 'max_value': _('Ensure this value is less than or equal to %(limit_value)s.'), 'min_value': _('Ensure this value is greater than or equal to %(limit_value)s.'), 'max_digits': _('Ensure that there are no more than %s digits in total.'), 'max_decimal_places': _('Ensure that there are no more than %s decimal places.'), 'max_whole_digits': _('Ensure that there are no more than %s digits before the decimal point.') } def __init__(self, max_value=None, min_value=None, max_digits=None, decimal_places=None, *args, **kwargs): self.max_value, self.min_value = max_value, min_value self.max_digits, self.decimal_places = max_digits, decimal_places Field.__init__(self, *args, **kwargs) if max_value is not None: self.validators.append(validators.MaxValueValidator(max_value)) if min_value is not None: self.validators.append(validators.MinValueValidator(min_value)) super(DecimalField, self).__init__(max_value, min_value, *args, **kwargs) def to_python(self, value): """ Loading Loading @@ -345,6 +355,19 @@ class DecimalField(Field): raise ValidationError(self.error_messages['max_whole_digits'] % (self.max_digits - self.decimal_places)) return value def widget_attrs(self, widget): attrs = super(DecimalField, self).widget_attrs(widget) if isinstance(widget, NumberInput): if self.max_digits is not None: max_length = self.max_digits + 1 # for the sign if self.decimal_places is None or self.decimal_places > 0: max_length += 1 # for the dot attrs['maxlength'] = max_length if self.decimal_places: attrs['step'] = '0.%s1' % ('0' * (self.decimal_places-1)) return attrs class BaseTemporalField(Field): def __init__(self, input_formats=None, *args, **kwargs): Loading django/forms/widgets.py +5 −1 Original line number Diff line number Diff line Loading @@ -23,7 +23,7 @@ from django.utils import datetime_safe, formats, six __all__ = ( 'Media', 'MediaDefiningClass', 'Widget', 'TextInput', 'EmailInput', 'URLInput', 'PasswordInput', 'EmailInput', 'URLInput', 'NumberInput', 'PasswordInput', 'HiddenInput', 'MultipleHiddenInput', 'ClearableFileInput', 'FileInput', 'DateInput', 'DateTimeInput', 'TimeInput', 'Textarea', 'CheckboxInput', 'Select', 'NullBooleanSelect', 'SelectMultiple', 'RadioSelect', Loading Loading @@ -252,6 +252,10 @@ class TextInput(Input): super(TextInput, self).__init__(attrs) class NumberInput(TextInput): input_type = 'number' class EmailInput(TextInput): input_type = 'email' Loading docs/ref/forms/fields.txt +6 −3 Original line number Diff line number Diff line Loading @@ -454,7 +454,8 @@ For each field, we describe the default widget used if you don't specify .. class:: DecimalField(**kwargs) * Default widget: :class:`TextInput` * Default widget: :class:`NumberInput` when :attr:`Field.localize` is ``False``, else :class:`TextInput`. * Empty value: ``None`` * Normalizes to: A Python ``decimal``. * Validates that the given value is a decimal. Leading and trailing Loading Loading @@ -580,7 +581,8 @@ For each field, we describe the default widget used if you don't specify .. class:: FloatField(**kwargs) * Default widget: :class:`TextInput` * Default widget: :class:`NumberInput` when :attr:`Field.localize` is ``False``, else :class:`TextInput`. * Empty value: ``None`` * Normalizes to: A Python float. * Validates that the given value is an float. Leading and trailing Loading Loading @@ -621,7 +623,8 @@ For each field, we describe the default widget used if you don't specify .. class:: IntegerField(**kwargs) * Default widget: :class:`TextInput` * Default widget: :class:`NumberInput` when :attr:`Field.localize` is ``False``, else :class:`TextInput`. * Empty value: ``None`` * Normalizes to: A Python integer or long integer. * Validates that the given value is an integer. Leading and trailing Loading docs/ref/forms/widgets.txt +13 −0 Original line number Diff line number Diff line Loading @@ -389,6 +389,19 @@ These widgets make use of the HTML elements ``input`` and ``textarea``. Text input: ``<input type="text" ...>`` ``NumberInput`` ~~~~~~~~~~~~~~~ .. class:: NumberInput .. versionadded:: 1.6 Text input: ``<input type="number" ...>`` Beware that not all browsers support entering localized numbers in ``number`` input types. Django itself avoids using them for fields having their :attr:`~django.forms.Field.localize` property to ``True``. ``EmailInput`` ~~~~~~~~~~~~~~ Loading docs/releases/1.6.txt +9 −4 Original line number Diff line number Diff line Loading @@ -60,9 +60,13 @@ Minor features * In addition to :lookup:`year`, :lookup:`month` and :lookup:`day`, the ORM now supports :lookup:`hour`, :lookup:`minute` and :lookup:`second` lookups. * The default widgets for :class:`~django.forms.EmailField` and :class:`~django.forms.URLField` use the new type attributes available in HTML5 (type='email', type='url'). * The default widgets for :class:`~django.forms.EmailField`, :class:`~django.forms.URLField`, :class:`~django.forms.IntegerField`, :class:`~django.forms.FloatField` and :class:`~django.forms.DecimalField` use the new type attributes available in HTML5 (type='email', type='url', type='number'). Note that due to erratic support of the ``number`` input type with localized numbers in current browsers, Django only uses it when numeric fields are not localized. * The ``number`` argument for :ref:`lazy plural translations <lazy-plural-translations>` can be provided at translation time rather than Loading Loading @@ -122,7 +126,8 @@ Backwards incompatible changes in 1.6 * If your CSS/Javascript code used to access HTML input widgets by type, you should review it as ``type='text'`` widgets might be now output as ``type='email'`` or ``type='url'`` depending on their corresponding field type. ``type='email'``, ``type='url'`` or ``type='number'`` depending on their corresponding field type. * Extraction of translatable literals from templates with the :djadmin:`makemessages` command now correctly detects i18n constructs when Loading Loading
django/forms/fields.py +34 −11 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ from django.core import validators from django.core.exceptions import ValidationError from django.forms.util import ErrorList, from_current_timezone, to_current_timezone from django.forms.widgets import ( TextInput, PasswordInput, EmailInput, URLInput, HiddenInput, TextInput, NumberInput, EmailInput, URLInput, HiddenInput, MultipleHiddenInput, ClearableFileInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple, DateInput, DateTimeInput, TimeInput, SplitDateTimeWidget, SplitHiddenDateTimeWidget, FILE_INPUT_CONTRADICTION Loading Loading @@ -234,6 +234,7 @@ class IntegerField(Field): def __init__(self, max_value=None, min_value=None, *args, **kwargs): self.max_value, self.min_value = max_value, min_value kwargs.setdefault('widget', NumberInput if not kwargs.get('localize') else self.widget) super(IntegerField, self).__init__(*args, **kwargs) if max_value is not None: Loading @@ -257,6 +258,16 @@ class IntegerField(Field): raise ValidationError(self.error_messages['invalid']) return value def widget_attrs(self, widget): attrs = super(IntegerField, self).widget_attrs(widget) if isinstance(widget, NumberInput): if self.min_value is not None: attrs['min'] = self.min_value if self.max_value is not None: attrs['max'] = self.max_value return attrs class FloatField(IntegerField): default_error_messages = { 'invalid': _('Enter a number.'), Loading @@ -278,25 +289,24 @@ class FloatField(IntegerField): raise ValidationError(self.error_messages['invalid']) return value class DecimalField(Field): def widget_attrs(self, widget): attrs = super(FloatField, self).widget_attrs(widget) if isinstance(widget, NumberInput): attrs.setdefault('step', 'any') return attrs class DecimalField(IntegerField): default_error_messages = { 'invalid': _('Enter a number.'), 'max_value': _('Ensure this value is less than or equal to %(limit_value)s.'), 'min_value': _('Ensure this value is greater than or equal to %(limit_value)s.'), 'max_digits': _('Ensure that there are no more than %s digits in total.'), 'max_decimal_places': _('Ensure that there are no more than %s decimal places.'), 'max_whole_digits': _('Ensure that there are no more than %s digits before the decimal point.') } def __init__(self, max_value=None, min_value=None, max_digits=None, decimal_places=None, *args, **kwargs): self.max_value, self.min_value = max_value, min_value self.max_digits, self.decimal_places = max_digits, decimal_places Field.__init__(self, *args, **kwargs) if max_value is not None: self.validators.append(validators.MaxValueValidator(max_value)) if min_value is not None: self.validators.append(validators.MinValueValidator(min_value)) super(DecimalField, self).__init__(max_value, min_value, *args, **kwargs) def to_python(self, value): """ Loading Loading @@ -345,6 +355,19 @@ class DecimalField(Field): raise ValidationError(self.error_messages['max_whole_digits'] % (self.max_digits - self.decimal_places)) return value def widget_attrs(self, widget): attrs = super(DecimalField, self).widget_attrs(widget) if isinstance(widget, NumberInput): if self.max_digits is not None: max_length = self.max_digits + 1 # for the sign if self.decimal_places is None or self.decimal_places > 0: max_length += 1 # for the dot attrs['maxlength'] = max_length if self.decimal_places: attrs['step'] = '0.%s1' % ('0' * (self.decimal_places-1)) return attrs class BaseTemporalField(Field): def __init__(self, input_formats=None, *args, **kwargs): Loading
django/forms/widgets.py +5 −1 Original line number Diff line number Diff line Loading @@ -23,7 +23,7 @@ from django.utils import datetime_safe, formats, six __all__ = ( 'Media', 'MediaDefiningClass', 'Widget', 'TextInput', 'EmailInput', 'URLInput', 'PasswordInput', 'EmailInput', 'URLInput', 'NumberInput', 'PasswordInput', 'HiddenInput', 'MultipleHiddenInput', 'ClearableFileInput', 'FileInput', 'DateInput', 'DateTimeInput', 'TimeInput', 'Textarea', 'CheckboxInput', 'Select', 'NullBooleanSelect', 'SelectMultiple', 'RadioSelect', Loading Loading @@ -252,6 +252,10 @@ class TextInput(Input): super(TextInput, self).__init__(attrs) class NumberInput(TextInput): input_type = 'number' class EmailInput(TextInput): input_type = 'email' Loading
docs/ref/forms/fields.txt +6 −3 Original line number Diff line number Diff line Loading @@ -454,7 +454,8 @@ For each field, we describe the default widget used if you don't specify .. class:: DecimalField(**kwargs) * Default widget: :class:`TextInput` * Default widget: :class:`NumberInput` when :attr:`Field.localize` is ``False``, else :class:`TextInput`. * Empty value: ``None`` * Normalizes to: A Python ``decimal``. * Validates that the given value is a decimal. Leading and trailing Loading Loading @@ -580,7 +581,8 @@ For each field, we describe the default widget used if you don't specify .. class:: FloatField(**kwargs) * Default widget: :class:`TextInput` * Default widget: :class:`NumberInput` when :attr:`Field.localize` is ``False``, else :class:`TextInput`. * Empty value: ``None`` * Normalizes to: A Python float. * Validates that the given value is an float. Leading and trailing Loading Loading @@ -621,7 +623,8 @@ For each field, we describe the default widget used if you don't specify .. class:: IntegerField(**kwargs) * Default widget: :class:`TextInput` * Default widget: :class:`NumberInput` when :attr:`Field.localize` is ``False``, else :class:`TextInput`. * Empty value: ``None`` * Normalizes to: A Python integer or long integer. * Validates that the given value is an integer. Leading and trailing Loading
docs/ref/forms/widgets.txt +13 −0 Original line number Diff line number Diff line Loading @@ -389,6 +389,19 @@ These widgets make use of the HTML elements ``input`` and ``textarea``. Text input: ``<input type="text" ...>`` ``NumberInput`` ~~~~~~~~~~~~~~~ .. class:: NumberInput .. versionadded:: 1.6 Text input: ``<input type="number" ...>`` Beware that not all browsers support entering localized numbers in ``number`` input types. Django itself avoids using them for fields having their :attr:`~django.forms.Field.localize` property to ``True``. ``EmailInput`` ~~~~~~~~~~~~~~ Loading
docs/releases/1.6.txt +9 −4 Original line number Diff line number Diff line Loading @@ -60,9 +60,13 @@ Minor features * In addition to :lookup:`year`, :lookup:`month` and :lookup:`day`, the ORM now supports :lookup:`hour`, :lookup:`minute` and :lookup:`second` lookups. * The default widgets for :class:`~django.forms.EmailField` and :class:`~django.forms.URLField` use the new type attributes available in HTML5 (type='email', type='url'). * The default widgets for :class:`~django.forms.EmailField`, :class:`~django.forms.URLField`, :class:`~django.forms.IntegerField`, :class:`~django.forms.FloatField` and :class:`~django.forms.DecimalField` use the new type attributes available in HTML5 (type='email', type='url', type='number'). Note that due to erratic support of the ``number`` input type with localized numbers in current browsers, Django only uses it when numeric fields are not localized. * The ``number`` argument for :ref:`lazy plural translations <lazy-plural-translations>` can be provided at translation time rather than Loading Loading @@ -122,7 +126,8 @@ Backwards incompatible changes in 1.6 * If your CSS/Javascript code used to access HTML input widgets by type, you should review it as ``type='text'`` widgets might be now output as ``type='email'`` or ``type='url'`` depending on their corresponding field type. ``type='email'``, ``type='url'`` or ``type='number'`` depending on their corresponding field type. * Extraction of translatable literals from templates with the :djadmin:`makemessages` command now correctly detects i18n constructs when Loading