Ticket #16630: html5-input-types-take2.patch

File html5-input-types-take2.patch, 7.8 KB (added by Jonas H., 12 years ago)

against [17281]

  • django/forms/fields.py

    commit 398d95e2fe9e759a60b7519793ce012662f392fa
    Author: Jonas Haag <jonas@lophus.org>
    Date:   Sun Aug 14 20:17:26 2011 +0200
    
        code
    
    diff --git a/django/forms/fields.py b/django/forms/fields.py
    index 0ba7467..aab34de 100644
    a b except ImportError:  
    1818from django.core import validators
    1919from django.core.exceptions import ValidationError
    2020from django.forms.util import ErrorList, from_current_timezone, to_current_timezone
    21 from django.forms.widgets import (TextInput, PasswordInput, HiddenInput,
     21from django.forms.widgets import (
     22    TextInput, IntegerInput, PasswordInput, EmailInput, URLInput, HiddenInput,
    2223    MultipleHiddenInput, ClearableFileInput, CheckboxInput, Select,
    2324    NullBooleanSelect, SelectMultiple, DateInput, DateTimeInput, TimeInput,
    24     SplitDateTimeWidget, SplitHiddenDateTimeWidget, FILE_INPUT_CONTRADICTION)
     25    SplitDateTimeWidget, SplitHiddenDateTimeWidget, FILE_INPUT_CONTRADICTION
     26)
    2527from django.utils import formats
    2628from django.utils.encoding import smart_unicode, smart_str, force_unicode
    2729from django.utils.ipv6 import clean_ipv6_address
    from django.utils.translation import ugettext_lazy as _  
    3032# Provide this import for backwards compatibility.
    3133from django.core.validators import EMPTY_VALUES
    3234
    33 
    3435__all__ = (
    3536    'Field', 'CharField', 'IntegerField',
    3637    'DateField', 'TimeField', 'DateTimeField', 'TimeField',
    class CharField(Field):  
    198199
    199200    def widget_attrs(self, widget):
    200201        attrs = super(CharField, self).widget_attrs(widget)
    201         if self.max_length is not None and isinstance(widget, (TextInput, PasswordInput)):
     202        if self.max_length is not None and isinstance(widget, TextInput):
    202203            # The HTML attribute is maxlength, not max_length.
    203204            attrs.update({'maxlength': str(self.max_length)})
    204205        return attrs
    205206
    206207class IntegerField(Field):
     208    widget = IntegerInput
    207209    default_error_messages = {
    208210        'invalid': _(u'Enter a whole number.'),
    209211        'max_value': _(u'Ensure this value is less than or equal to %(limit_value)s.'),
    class IntegerField(Field):  
    235237            raise ValidationError(self.error_messages['invalid'])
    236238        return value
    237239
     240    def widget_attrs(self, widget):
     241        attrs = super(IntegerField, self).widget_attrs(widget)
     242        if self.min_value:
     243            attrs['min'] = self.min_value
     244        if self.max_value:
     245            attrs['max'] = self.max_value
     246        return attrs
     247
    238248class FloatField(IntegerField):
    239249    default_error_messages = {
    240250        'invalid': _(u'Enter a number.'),
    class FloatField(IntegerField):  
    256266            raise ValidationError(self.error_messages['invalid'])
    257267        return value
    258268
    259 class DecimalField(Field):
     269    def widget_attrs(self, widget):
     270        attrs = super(FloatField, self).widget_attrs(widget)
     271        attrs['step'] = 'any'
     272        return attrs
     273
     274class DecimalField(IntegerField):
    260275    default_error_messages = {
    261276        'invalid': _(u'Enter a number.'),
    262         'max_value': _(u'Ensure this value is less than or equal to %(limit_value)s.'),
    263         'min_value': _(u'Ensure this value is greater than or equal to %(limit_value)s.'),
    264277        'max_digits': _('Ensure that there are no more than %s digits in total.'),
    265278        'max_decimal_places': _('Ensure that there are no more than %s decimal places.'),
    266279        'max_whole_digits': _('Ensure that there are no more than %s digits before the decimal point.')
    267280    }
    268281
    269282    def __init__(self, max_value=None, min_value=None, max_digits=None, decimal_places=None, *args, **kwargs):
    270         self.max_value, self.min_value = max_value, min_value
    271283        self.max_digits, self.decimal_places = max_digits, decimal_places
    272         Field.__init__(self, *args, **kwargs)
    273 
    274         if max_value is not None:
    275             self.validators.append(validators.MaxValueValidator(max_value))
    276         if min_value is not None:
    277             self.validators.append(validators.MinValueValidator(min_value))
     284        super(DecimalField, self).__init__(max_value, min_value, *args, **kwargs)
    278285
    279286    def to_python(self, value):
    280287        """
    class DecimalField(Field):  
    323330            raise ValidationError(self.error_messages['max_whole_digits'] % (self.max_digits - self.decimal_places))
    324331        return value
    325332
     333    def widget_attrs(self, widget):
     334        attrs = super(DecimalField, self).widget_attrs(widget)
     335        if self.max_digits:
     336            attrs['maxlength'] = self.max_digits + 1 # for the dot
     337        if self.decimal_places:
     338            attrs['step'] = '0.%s1' % ('0' * (self.decimal_places-1))
     339        return attrs
     340
    326341class BaseTemporalField(Field):
    327342
    328343    def __init__(self, input_formats=None, *args, **kwargs):
    class RegexField(CharField):  
    470485    regex = property(_get_regex, _set_regex)
    471486
    472487class EmailField(CharField):
     488    widget = EmailInput
    473489    default_error_messages = {
    474490        'invalid': _(u'Enter a valid e-mail address.'),
    475491    }
    class ImageField(FileField):  
    596612        return f
    597613
    598614class URLField(CharField):
     615    widget = URLInput
    599616    default_error_messages = {
    600617        'invalid': _(u'Enter a valid URL.'),
    601618        'invalid_link': _(u'This URL appears to be a broken link.'),
  • django/forms/widgets.py

    diff --git a/django/forms/widgets.py b/django/forms/widgets.py
    index 49b148e..082eae3 100644
    a b from django.utils.safestring import mark_safe  
    1919from django.utils import datetime_safe, formats
    2020
    2121__all__ = (
    22     'Media', 'MediaDefiningClass', 'Widget', 'TextInput', 'PasswordInput',
    23     'HiddenInput', 'MultipleHiddenInput', 'ClearableFileInput',
    24     'FileInput', 'DateInput', 'DateTimeInput', 'TimeInput', 'Textarea', 'CheckboxInput',
    25     'Select', 'NullBooleanSelect', 'SelectMultiple', 'RadioSelect',
    26     'CheckboxSelectMultiple', 'MultiWidget',
    27     'SplitDateTimeWidget',
     22    'Media', 'MediaDefiningClass', 'Widget', 'TextInput', 'EmailInput', 'URLInput',
     23    'IntegerInput', 'PasswordInput', 'HiddenInput', 'MultipleHiddenInput',
     24    'ClearableFileInput', 'FileInput', 'DateInput', 'DateTimeInput', 'TimeInput',
     25    'Textarea', 'CheckboxInput', 'Select', 'NullBooleanSelect', 'SelectMultiple',
     26    'RadioSelect', 'CheckboxSelectMultiple', 'MultiWidget', 'SplitDateTimeWidget',
    2827)
    2928
    3029MEDIA_TYPES = ('css','js')
    class Input(Widget):  
    260259class TextInput(Input):
    261260    input_type = 'text'
    262261
    263 class PasswordInput(Input):
     262class IntegerInput(TextInput):
     263    input_type = 'number'
     264
     265class EmailInput(TextInput):
     266    input_type = 'email'
     267
     268class URLInput(TextInput):
     269    input_type = 'url'
     270
     271class PasswordInput(TextInput):
    264272    input_type = 'password'
    265273
    266274    def __init__(self, attrs=None, render_value=False):
    class Textarea(Widget):  
    396404        return mark_safe(u'<textarea%s>%s</textarea>' % (flatatt(final_attrs),
    397405                conditional_escape(force_unicode(value))))
    398406
    399 class DateInput(Input):
    400     input_type = 'text'
    401 
     407class DateInput(TextInput):
    402408    def __init__(self, attrs=None, format=None):
    403409        super(DateInput, self).__init__(attrs)
    404410        if format:
    class DateInput(Input):  
    427433            pass
    428434        return super(DateInput, self)._has_changed(self._format_value(initial), data)
    429435
    430 class DateTimeInput(Input):
    431     input_type = 'text'
    432 
     436class DateTimeInput(TextInput):
    433437    def __init__(self, attrs=None, format=None):
    434438        super(DateTimeInput, self).__init__(attrs)
    435439        if format:
    class DateTimeInput(Input):  
    458462            pass
    459463        return super(DateTimeInput, self)._has_changed(self._format_value(initial), data)
    460464
    461 class TimeInput(Input):
    462     input_type = 'text'
    463 
     465class TimeInput(TextInput):
    464466    def __init__(self, attrs=None, format=None):
    465467        super(TimeInput, self).__init__(attrs)
    466468        if format:
Back to Top