Django

Code

Ticket #6362: 6362.normalize-kwarg.diff

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

normalize kwarg for newforms.Field

  • django/newforms/fields.py

    old new  
    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

    old new  
    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

    old new  
    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