summaryrefslogtreecommitdiff
path: root/django/forms
diff options
context:
space:
mode:
authorClaude Paroz <claude@2xlibre.net>2013-02-23 09:45:56 +0100
committerClaude Paroz <claude@2xlibre.net>2013-02-23 10:18:08 +0100
commit7ec2a21be15af5b2c7513482c3bcfdd1e12782ed (patch)
tree13c7d8bdaca60c246d6de8166ad3f66f04dc7a58 /django/forms
parentdcf651c27edff13236fda0a480059b57dbe6e074 (diff)
Fixed #19686 -- Added HTML5 number input type
Thanks Simon Charette for his help on the patch. Refs #16630.
Diffstat (limited to 'django/forms')
-rw-r--r--django/forms/fields.py45
-rw-r--r--django/forms/widgets.py6
2 files changed, 39 insertions, 12 deletions
diff --git a/django/forms/fields.py b/django/forms/fields.py
index c547d1456c..621d3801f2 100644
--- a/django/forms/fields.py
+++ b/django/forms/fields.py
@@ -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
@@ -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:
@@ -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.'),
@@ -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):
"""
@@ -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):
diff --git a/django/forms/widgets.py b/django/forms/widgets.py
index e906ed5bc6..026e8dc36a 100644
--- a/django/forms/widgets.py
+++ b/django/forms/widgets.py
@@ -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',
@@ -252,6 +252,10 @@ class TextInput(Input):
super(TextInput, self).__init__(attrs)
+class NumberInput(TextInput):
+ input_type = 'number'
+
+
class EmailInput(TextInput):
input_type = 'email'