Ticket #6362: 6362.normalize-kwarg.diff

File 6362.normalize-kwarg.diff, 6.8 KB (added by emulbreh, 7 years ago)

normalize kwarg for newforms.Field

  • django/newforms/fields.py

     
    5656    creation_counter = 0
    5757
    5858    def __init__(self, required=True, widget=None, label=None, initial=None,
    59                  help_text=None, error_messages=None):
     59                 help_text=None, error_messages=None, normalize=None):
    6060        # required -- Boolean that specifies whether the field is required.
    6161        #             True by default.
    6262        # widget -- A Widget class, or instance of a Widget class, that should
     
    7474            label = smart_unicode(label)
    7575        self.required, self.label, self.initial = required, label, initial
    7676        self.help_text = smart_unicode(help_text or '')
     77        self.normalize = normalize
    7778        widget = widget or self.widget
    7879        if isinstance(widget, type):
    7980            widget = widget()
     
    106107
    107108        Raises ValidationError for any errors.
    108109        """
     110        if self.normalize:
     111            value = self.normalize(value)
    109112        if self.required and value in EMPTY_VALUES:
    110113            raise ValidationError(self.error_messages['required'])
    111114        return value
     
    136139
    137140    def clean(self, value):
    138141        "Validates max_length and min_length. Returns a Unicode object."
    139         super(CharField, self).clean(value)
     142        value = super(CharField, self).clean(value)
    140143        if value in EMPTY_VALUES:
    141144            return u''
    142145        value = smart_unicode(value)
     
    168171        Validates that int() can be called on the input. Returns the result
    169172        of int(). Returns None for empty values.
    170173        """
    171         super(IntegerField, self).clean(value)
     174        value = super(IntegerField, self).clean(value)
    172175        if value in EMPTY_VALUES:
    173176            return None
    174177        try:
     
    197200        Validates that float() can be called on the input. Returns a float.
    198201        Returns None for empty values.
    199202        """
    200         super(FloatField, self).clean(value)
     203        value = super(FloatField, self).clean(value)
    201204        if not self.required and value in EMPTY_VALUES:
    202205            return None
    203206        try:
     
    232235        than max_digits in the number, and no more than decimal_places digits
    233236        after the decimal point.
    234237        """
    235         super(DecimalField, self).clean(value)
     238        value = super(DecimalField, self).clean(value)
    236239        if not self.required and value in EMPTY_VALUES:
    237240            return None
    238241        value = smart_str(value).strip()
     
    277280        Validates that the input can be converted to a date. Returns a Python
    278281        datetime.date object.
    279282        """
    280         super(DateField, self).clean(value)
     283        value = super(DateField, self).clean(value)
    281284        if value in EMPTY_VALUES:
    282285            return None
    283286        if isinstance(value, datetime.datetime):
     
    310313        Validates that the input can be converted to a time. Returns a Python
    311314        datetime.time object.
    312315        """
    313         super(TimeField, self).clean(value)
     316        value = super(TimeField, self).clean(value)
    314317        if value in EMPTY_VALUES:
    315318            return None
    316319        if isinstance(value, datetime.time):
     
    349352        Validates that the input can be converted to a datetime. Returns a
    350353        Python datetime.datetime object.
    351354        """
    352         super(DateTimeField, self).clean(value)
     355        value = super(DateTimeField, self).clean(value)
    353356        if value in EMPTY_VALUES:
    354357            return None
    355358        if isinstance(value, datetime.datetime):
     
    444447        super(FileField, self).__init__(*args, **kwargs)
    445448
    446449    def clean(self, data, initial=None):
    447         super(FileField, self).clean(initial or data)
     450        value = super(FileField, self).clean(initial or data)
    448451        if not self.required and data in EMPTY_VALUES:
    449452            return None
    450453        elif not data and initial:
     
    572575
    573576class BooleanField(Field):
    574577    widget = CheckboxInput
    575 
    576     def clean(self, value):
    577         """Returns a Python boolean object."""
     578    def __init__(self, normalize=None, *args, **kwargs):
    578579        # Explicitly check for the string 'False', which is what a hidden field
    579580        # will submit for False. Because bool("True") == True, we don't need to
    580581        # handle that explicitly.
    581         if value == 'False':
    582             value = False
     582        bool_norm = lambda value: value != 'False' and bool(value)
     583        if normalize:
     584            norm_func = lambda value: bool_norm(normalize(value))
    583585        else:
    584             value = bool(value)
    585         super(BooleanField, self).clean(value)
     586            norm_func = bool_norm
     587        super(BooleanField, self).__init__(normalize=norm_func, *args, **kwargs)
     588
     589    def clean(self, value):
     590        """Returns a Python boolean object."""
     591        value = super(BooleanField, self).clean(value)
    586592        if not value and self.required:
    587593            raise ValidationError(self.error_messages['required'])
    588594        return value
     
    679685        Validates the given value against all of self.fields, which is a
    680686        list of Field instances.
    681687        """
    682         super(ComboField, self).clean(value)
     688        value = super(ComboField, self).clean(value)
    683689        for field in self.fields:
    684690            value = field.clean(value)
    685691        return value
  • tests/regressiontests/forms/fields.py

     
    104104>>> f.clean('1234567890a')
    105105u'1234567890a'
    106106
     107Normalize away leading and trailing whitspace:
     108>>> f = CharField(normalize=lambda x: x.strip())
     109>>> f.clean("  \t")
     110Traceback (most recent call last):
     111...
     112ValidationError: [u'This field is required.']
     113
    107114# IntegerField ################################################################
    108115
    109116>>> f = IntegerField()
  • docs/newforms.txt

     
    11321132In the `built-in Field classes`_ section below, each ``Field`` defines the
    11331133error message keys it uses.
    11341134
     1135``normalize``
     1136~~~~~~~~~~~~~
     1137
     1138**New in Django development version**
     1139
     1140The ``normalize`` argument lets you normalize the input data before it is validated.
     1141A common use-case is stripping leading and trailinig whitespace from CharFields::
     1142
     1143    >>> foo = forms.CharField(normalize=lambda x: x.strip())
     1144    >>> foo.clean('   ')
     1145    Traceback (most recent call last):
     1146      ...
     1147    ValidationError: [u'This field is required.']   
     1148
    11351149Dynamic initial values
    11361150----------------------
    11371151
Back to Top