Django

Code

Changeset 6625

Show
Ignore:
Timestamp:
10/28/07 00:40:26 (10 months ago)
Author:
gwilson
Message:

Fixed #3457 -- Allow overridding of error messages for newforms Fields.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/newforms/fields.py

    r6623 r6625  
    1717    from sets import Set as set 
    1818 
    19 from django.utils.translation import ugettext 
     19from django.utils.translation import ugettext_lazy 
    2020from django.utils.encoding import StrAndUnicode, smart_unicode 
    2121 
     
    4242    widget = TextInput # Default widget to use when rendering this type of Field. 
    4343    hidden_widget = HiddenInput # Default widget to use when rendering this as "hidden". 
     44    default_error_messages = { 
     45        'required': ugettext_lazy(u'This field is required.'), 
     46        'invalid': ugettext_lazy(u'Enter a valid value.'), 
     47    } 
    4448 
    4549    # Tracks each time a Field instance is created. Used to retain order. 
    4650    creation_counter = 0 
    4751 
    48     def __init__(self, required=True, widget=None, label=None, initial=None, help_text=None): 
     52    def __init__(self, required=True, widget=None, label=None, initial=None, 
     53                 help_text=None, error_messages=None): 
    4954        # required -- Boolean that specifies whether the field is required. 
    5055        #             True by default. 
     
    7984        Field.creation_counter += 1 
    8085 
     86        self.error_messages = self._build_error_messages(error_messages) 
     87 
     88    def _build_error_messages(self, extra_error_messages): 
     89        error_messages = {} 
     90        def get_default_error_messages(klass): 
     91            for base_class in klass.__bases__: 
     92                get_default_error_messages(base_class) 
     93            if hasattr(klass, 'default_error_messages'): 
     94                error_messages.update(klass.default_error_messages) 
     95        get_default_error_messages(self.__class__) 
     96        if extra_error_messages: 
     97            error_messages.update(extra_error_messages) 
     98        return error_messages 
     99 
    81100    def clean(self, value): 
    82101        """ 
     
    87106        """ 
    88107        if self.required and value in EMPTY_VALUES: 
    89             raise ValidationError(ugettext(u'This field is required.')
     108            raise ValidationError(self.error_messages['required']
    90109        return value 
    91110 
     
    105124 
    106125class CharField(Field): 
     126    default_error_messages = { 
     127        'max_length': ugettext_lazy(u'Ensure this value has at most %(max)d characters (it has %(length)d).'), 
     128        'min_length': ugettext_lazy(u'Ensure this value has at least %(min)d characters (it has %(length)d).'), 
     129    } 
     130 
    107131    def __init__(self, max_length=None, min_length=None, *args, **kwargs): 
    108132        self.max_length, self.min_length = max_length, min_length 
     
    117141        value_length = len(value) 
    118142        if self.max_length is not None and value_length > self.max_length: 
    119             raise ValidationError(ugettext(u'Ensure this value has at most %(max)d characters (it has %(length)d).') % {'max': self.max_length, 'length': value_length}) 
     143            raise ValidationError(self.error_messages['max_length'] % {'max': self.max_length, 'length': value_length}) 
    120144        if self.min_length is not None and value_length < self.min_length: 
    121             raise ValidationError(ugettext(u'Ensure this value has at least %(min)d characters (it has %(length)d).') % {'min': self.min_length, 'length': value_length}) 
     145            raise ValidationError(self.error_messages['min_length'] % {'min': self.min_length, 'length': value_length}) 
    122146        return value 
    123147 
     
    128152 
    129153class IntegerField(Field): 
     154    default_error_messages = { 
     155        'invalid': ugettext_lazy(u'Enter a whole number.'), 
     156        'max_value': ugettext_lazy(u'Ensure this value is less than or equal to %s.'), 
     157        'min_value': ugettext_lazy(u'Ensure this value is greater than or equal to %s.'), 
     158    } 
     159 
    130160    def __init__(self, max_value=None, min_value=None, *args, **kwargs): 
    131161        self.max_value, self.min_value = max_value, min_value 
     
    143173            value = int(str(value)) 
    144174        except (ValueError, TypeError): 
    145             raise ValidationError(ugettext(u'Enter a whole number.')
     175            raise ValidationError(self.error_messages['invalid']
    146176        if self.max_value is not None and value > self.max_value: 
    147             raise ValidationError(ugettext(u'Ensure this value is less than or equal to %s.') % self.max_value) 
     177            raise ValidationError(self.error_messages['max_value'] % self.max_value) 
    148178        if self.min_value is not None and value < self.min_value: 
    149             raise ValidationError(ugettext(u'Ensure this value is greater than or equal to %s.') % self.min_value) 
     179            raise ValidationError(self.error_messages['min_value'] % self.min_value) 
    150180        return value 
    151181 
    152182class FloatField(Field): 
     183    default_error_messages = { 
     184        'invalid': ugettext_lazy(u'Enter a number.'), 
     185        'max_value': ugettext_lazy(u'Ensure this value is less than or equal to %s.'), 
     186        'min_value': ugettext_lazy(u'Ensure this value is greater than or equal to %s.'), 
     187    } 
     188 
    153189    def __init__(self, max_value=None, min_value=None, *args, **kwargs): 
    154190        self.max_value, self.min_value = max_value, min_value 
     
    166202            value = float(value) 
    167203        except (ValueError, TypeError): 
    168             raise ValidationError(ugettext('Enter a number.')
     204            raise ValidationError(self.error_messages['invalid']
    169205        if self.max_value is not None and value > self.max_value: 
    170             raise ValidationError(ugettext('Ensure this value is less than or equal to %s.') % self.max_value) 
     206            raise ValidationError(self.error_messages['max_value'] % self.max_value) 
    171207        if self.min_value is not None and value < self.min_value: 
    172             raise ValidationError(ugettext('Ensure this value is greater than or equal to %s.') % self.min_value) 
     208            raise ValidationError(self.error_messages['min_value'] % self.min_value) 
    173209        return value 
    174210 
    175211class DecimalField(Field): 
     212    default_error_messages = { 
     213        'invalid': ugettext_lazy(u'Enter a number.'), 
     214        'max_value': ugettext_lazy(u'Ensure this value is less than or equal to %s.'), 
     215        'min_value': ugettext_lazy(u'Ensure this value is greater than or equal to %s.'), 
     216        'max_digits': ugettext_lazy('Ensure that there are no more than %s digits in total.'), 
     217        'max_decimal_places': ugettext_lazy('Ensure that there are no more than %s decimal places.'), 
     218        'max_whole_digits': ugettext_lazy('Ensure that there are no more than %s digits before the decimal point.') 
     219    } 
     220 
    176221    def __init__(self, max_value=None, min_value=None, max_digits=None, decimal_places=None, *args, **kwargs): 
    177222        self.max_value, self.min_value = max_value, min_value 
     
    193238            value = Decimal(value) 
    194239        except DecimalException: 
    195             raise ValidationError(ugettext('Enter a number.')
     240            raise ValidationError(self.error_messages['invalid']
    196241        pieces = str(value).lstrip("-").split('.') 
    197242        decimals = (len(pieces) == 2) and len(pieces[1]) or 0 
    198243        digits = len(pieces[0]) 
    199244        if self.max_value is not None and value > self.max_value: 
    200             raise ValidationError(ugettext('Ensure this value is less than or equal to %s.') % self.max_value) 
     245            raise ValidationError(self.error_messages['max_value'] % self.max_value) 
    201246        if self.min_value is not None and value < self.min_value: 
    202             raise ValidationError(ugettext('Ensure this value is greater than or equal to %s.') % self.min_value) 
     247            raise ValidationError(self.error_messages['min_value'] % self.min_value) 
    203248        if self.max_digits is not None and (digits + decimals) > self.max_digits: 
    204             raise ValidationError(ugettext('Ensure that there are no more than %s digits in total.') % self.max_digits) 
     249            raise ValidationError(self.error_messages['max_digits'] % self.max_digits) 
    205250        if self.decimal_places is not None and decimals > self.decimal_places: 
    206             raise ValidationError(ugettext('Ensure that there are no more than %s decimal places.') % self.decimal_places) 
     251            raise ValidationError(self.error_messages['max_decimal_places'] % self.decimal_places) 
    207252        if self.max_digits is not None and self.decimal_places is not None and digits > (self.max_digits - self.decimal_places): 
    208             raise ValidationError(ugettext('Ensure that there are no more than %s digits before the decimal point.') % (self.max_digits - self.decimal_places)) 
     253            raise ValidationError(self.error_messages['max_whole_digits'] % (self.max_digits - self.decimal_places)) 
    209254        return value 
    210255 
     
    218263 
    219264class DateField(Field): 
     265    default_error_messages = { 
     266        'invalid': ugettext_lazy(u'Enter a valid date.'), 
     267    } 
     268 
    220269    def __init__(self, input_formats=None, *args, **kwargs): 
    221270        super(DateField, self).__init__(*args, **kwargs) 
     
    239288            except ValueError: 
    240289                continue 
    241         raise ValidationError(ugettext(u'Enter a valid date.')
     290        raise ValidationError(self.error_messages['invalid']
    242291 
    243292DEFAULT_TIME_INPUT_FORMATS = ( 
     
    247296 
    248297class TimeField(Field): 
     298    default_error_messages = { 
     299        'invalid': ugettext_lazy(u'Enter a valid time.') 
     300    } 
     301 
    249302    def __init__(self, input_formats=None, *args, **kwargs): 
    250303        super(TimeField, self).__init__(*args, **kwargs) 
     
    266319            except ValueError: 
    267320                continue 
    268         raise ValidationError(ugettext(u'Enter a valid time.')
     321        raise ValidationError(self.error_messages['invalid']
    269322 
    270323DEFAULT_DATETIME_INPUT_FORMATS = ( 
     
    282335class DateTimeField(Field): 
    283336    widget = DateTimeInput 
     337    default_error_messages = { 
     338        'invalid': ugettext_lazy(u'Enter a valid date/time.'), 
     339    } 
    284340 
    285341    def __init__(self, input_formats=None, *args, **kwargs): 
     
    303359            # components: date and time. 
    304360            if len(value) != 2: 
    305                 raise ValidationError(ugettext(u'Enter a valid date/time.')
     361                raise ValidationError(self.error_messages['invalid']
    306362            value = '%s %s' % tuple(value) 
    307363        for format in self.input_formats: 
     
    310366            except ValueError: 
    311367                continue 
    312         raise ValidationError(ugettext(u'Enter a valid date/time.')
     368        raise ValidationError(self.error_messages['invalid']
    313369 
    314370class RegexField(CharField): 
     
    319375        'Enter a valid value' is too generic for you. 
    320376        """ 
     377        # error_message is just kept for backwards compatibility: 
     378        if error_message: 
     379            error_messages = kwargs.get('error_messages') or {} 
     380            error_messages['invalid'] = error_message 
     381            kwargs['error_messages'] = error_messages 
    321382        super(RegexField, self).__init__(max_length, min_length, *args, **kwargs) 
    322383        if isinstance(regex, basestring): 
    323384            regex = re.compile(regex) 
    324385        self.regex = regex 
    325         self.error_message = error_message or ugettext(u'Enter a valid value.') 
    326386 
    327387    def clean(self, value): 
     
    334394            return value 
    335395        if not self.regex.search(value): 
    336             raise ValidationError(self.error_message
     396            raise ValidationError(self.error_messages['invalid']
    337397        return value 
    338398 
     
    343403 
    344404class EmailField(RegexField): 
     405    default_error_messages = { 
     406        'invalid': ugettext_lazy(u'Enter a valid e-mail address.'), 
     407    } 
     408 
    345409    def __init__(self, max_length=None, min_length=None, *args, **kwargs): 
    346         RegexField.__init__(self, email_re, max_length, min_length, 
    347             ugettext(u'Enter a valid e-mail address.'), *args, **kwargs) 
     410        RegexField.__init__(self, email_re, max_length, min_length, *args, 
     411                            **kwargs) 
    348412 
    349413try: 
     
    369433class FileField(Field): 
    370434    widget = FileInput 
     435    default_error_messages = { 
     436        'invalid': ugettext_lazy(u"No file was submitted. Check the encoding type on the form."), 
     437        'missing': ugettext_lazy(u"No file was submitted."), 
     438        'empty': ugettext_lazy(u"The submitted file is empty."), 
     439    } 
     440 
    371441    def __init__(self, *args, **kwargs): 
    372442        super(FileField, self).__init__(*args, **kwargs) 
     
    379449            f = UploadedFile(data['filename'], data['content']) 
    380450        except TypeError: 
    381             raise ValidationError(ugettext(u"No file was submitted. Check the encoding type on the form.")
     451            raise ValidationError(self.error_messages['invalid']
    382452        except KeyError: 
    383             raise ValidationError(ugettext(u"No file was submitted.")
     453            raise ValidationError(self.error_messages['missing']
    384454        if not f.content: 
    385             raise ValidationError(ugettext(u"The submitted file is empty.")
     455            raise ValidationError(self.error_messages['empty']
    386456        return f 
    387457 
    388458class ImageField(FileField): 
     459    default_error_messages = { 
     460        'invalid_image': ugettext_lazy(u"Upload a valid image. The file you uploaded was either not an image or a corrupted image."), 
     461    } 
     462 
    389463    def clean(self, data): 
    390464        """ 
     
    407481            trial_image.verify() 
    408482        except Exception: # Python Imaging Library doesn't recognize it as an image 
    409             raise ValidationError(ugettext(u"Upload a valid image. The file you uploaded was either not an image or a corrupted image.")
     483            raise ValidationError(self.error_messages['invalid_image']
    410484        return f 
    411485 
     
    419493 
    420494class URLField(RegexField): 
     495    default_error_messages = { 
     496        'invalid': ugettext_lazy(u'Enter a valid URL.'), 
     497        'invalid_link': ugettext_lazy(u'This URL appears to be a broken link.'), 
     498    } 
     499 
    421500    def __init__(self, max_length=None, min_length=None, verify_exists=False, 
    422501            validator_user_agent=URL_VALIDATOR_USER_AGENT, *args, **kwargs): 
    423         super(URLField, self).__init__(url_re, max_length, min_length, ugettext(u'Enter a valid URL.'), *args, **kwargs) 
     502        super(URLField, self).__init__(url_re, max_length, min_length, *args, 
     503                                       **kwargs) 
    424504        self.verify_exists = verify_exists 
    425505        self.user_agent = validator_user_agent 
     
    446526                u = urllib2.urlopen(req) 
    447527            except ValueError: 
    448                 raise ValidationError(ugettext(u'Enter a valid URL.')
     528                raise ValidationError(self.error_messages['invalid']
    449529            except: # urllib2.URLError, httplib.InvalidURL, etc. 
    450                 raise ValidationError(ugettext(u'This URL appears to be a broken link.')
     530                raise ValidationError(self.error_messages['invalid_link']
    451531        return value 
    452532 
     
    475555class ChoiceField(Field): 
    476556    widget = Select 
    477  
    478     def __init__(self, choices=(), required=True, widget=None, label=None, initial=None, help_text=None): 
    479         super(ChoiceField, self).__init__(required, widget, label, initial, help_text) 
     557    default_error_messages = { 
     558        'invalid_choice': ugettext_lazy(u'Select a valid choice. That choice is not one of the available choices.'), 
     559    } 
     560 
     561    def __init__(self, choices=(), required=True, widget=None, label=None, 
     562                 initial=None, help_text=None, *args, **kwargs): 
     563        super(ChoiceField, self).__init__(required, widget, label, initial, 
     564                                          help_text, *args, **kwargs) 
    480565        self.choices = choices 
    481566 
     
    503588        valid_values = set([smart_unicode(k) for k, v in self.choices]) 
    504589        if value not in valid_values: 
    505             raise ValidationError(ugettext(u'Select a valid choice. That choice is not one of the available choices.')
     590            raise ValidationError(self.error_messages['invalid_choice'] % {'value': value}
    506591        return value 
    507592 
     
    509594    hidden_widget = MultipleHiddenInput 
    510595    widget = SelectMultiple 
     596    default_error_messages = { 
     597        'invalid_choice': ugettext_lazy(u'Select a valid choice. %(value)s is not one of the available choices.'), 
     598        'invalid_list': ugettext_lazy(u'Enter a list of values.'), 
     599    } 
    511600 
    512601    def clean(self, value): 
     
    515604        """ 
    516605        if self.required and not value: 
    517             raise ValidationError(ugettext(u'This field is required.')
     606            raise ValidationError(self.error_messages['required']
    518607        elif not self.required and not value: 
    519608            return [] 
    520609        if not isinstance(value, (list, tuple)): 
    521             raise ValidationError(ugettext(u'Enter a list of values.')
     610            raise ValidationError(self.error_messages['invalid_list']
    522611        new_value = [smart_unicode(val) for val in value] 
    523612        # Validate that each value in the value list is in self.choices. 
     
    525614        for val in new_value: 
    526615            if val not in valid_values: 
    527                 raise ValidationError(ugettext(u'Select a valid choice. %s is not one of the available choices.') % val
     616                raise ValidationError(self.error_messages['invalid_choice'] % {'value': val}
    528617        return new_value 
    529618 
     
    568657    You'll probably want to use this with MultiWidget. 
    569658    """ 
     659    default_error_messages = { 
     660        'invalid': ugettext_lazy(u'Enter a list of values.'), 
     661    } 
     662 
    570663    def __init__(self, fields=(), *args, **kwargs): 
    571664        super(MultiValueField, self).__init__(*args, **kwargs) 
     
    591684            if not value or not [v for v in value if v not in EMPTY_VALUES]: 
    592685                if self.required: 
    593                     raise ValidationError(ugettext(u'This field is required.')
     686                    raise ValidationError(self.error_messages['required']
    594687                else: 
    595688                    return self.compress([]) 
    596689        else: 
    597             raise ValidationError(ugettext(u'Enter a list of values.')
     690            raise ValidationError(self.error_messages['invalid']
    598691        for i, field in enumerate(self.fields): 
    599692            try: 
     
    602695                field_value = None 
    603696            if self.required and field_value in EMPTY_VALUES: 
    604                 raise ValidationError(ugettext(u'This field is required.')
     697                raise ValidationError(self.error_messages['required']
    605698            try: 
    606699                clean_data.append(field.clean(field_value)) 
     
    626719 
    627720class SplitDateTimeField(MultiValueField): 
     721    default_error_messages = { 
     722        'invalid_date': ugettext_lazy(u'Enter a valid date.'), 
     723        'invalid_time': ugettext_lazy(u'Enter a valid time.'), 
     724    } 
     725 
    628726    def __init__(self, *args, **kwargs): 
    629         fields = (DateField(), TimeField()) 
     727        errors = self.default_error_messages.copy() 
     728        if 'error_messages' in kwargs: 
     729            errors.update(kwargs['error_messages']) 
     730        fields = ( 
     731            DateField(error_messages={'invalid': errors['invalid_date']}), 
     732            TimeField(error_messages={'invalid': errors['invalid_time']}), 
     733        ) 
    630734        super(SplitDateTimeField, self).__init__(fields, *args, **kwargs) 
    631735 
     
    635739            # (possible if SplitDateTimeField has required=False). 
    636740            if data_list[0] in EMPTY_VALUES: 
    637                 raise ValidationError(ugettext(u'Enter a valid date.')
     741                raise ValidationError(self.error_messages['invalid_date']
    638742            if data_list[1] in EMPTY_VALUES: 
    639                 raise ValidationError(ugettext(u'Enter a valid time.')
     743                raise ValidationError(self.error_messages['invalid_time']
    640744            return datetime.datetime.combine(*data_list) 
    641745        return None 
     
    644748 
    645749class IPAddressField(RegexField): 
     750    default_error_messages = { 
     751        'invalid': ugettext_lazy(u'Enter a valid IPv4 address.'), 
     752    } 
     753 
    646754    def __init__(self, *args, **kwargs): 
    647         RegexField.__init__(self, ipv4_re, 
    648                             error_message=ugettext(u'Enter a valid IPv4 address.'), 
    649                             *args, **kwargs) 
     755        super(IPAddressField, self).__init__(ipv4_re, *args, **kwargs) 
  • django/trunk/django/newforms/util.py

    r6266 r6625  
    4343        return u'\n'.join([u'* %s' % force_unicode(e) for e in self]) 
    4444 
     45    def __repr__(self): 
     46        return repr([force_unicode(e) for e in self]) 
     47 
    4548class ValidationError(Exception): 
    4649    def __init__(self, message): 
    47         "ValidationError can be passed a string or a list." 
     50        """ 
     51        ValidationError can be passed any object that can be printed (usually 
     52        a string) or a list of objects. 
     53        """ 
    4854        if isinstance(message, list): 
    4955            self.messages = ErrorList([smart_unicode(msg) for msg in message]) 
    5056        else: 
    51             assert isinstance(message, (basestring, Promise)), ("%s should be a basestring or lazy translation" % repr(message)) 
    5257            message = smart_unicode(message) 
    5358            self.messages = ErrorList([message]) 
     
    5964        # See http://www.python.org/doc/current/tut/node10.html#handling 
    6065        return repr(self.messages) 
    61  
  • django/trunk/django/test/testcases.py

    r6164 r6625  
    147147                                        " error '%s' (actual errors: %s)" % 
    148148                                            (field, form, i, err, 
    149                                              list(field_errors))) 
     149                                             repr(field_errors))) 
    150150                    elif field in context[form].fields: 
    151151                        self.fail("The field '%s' on form '%s' in context %d" 
  • django/trunk/docs/newforms.txt

    r6578 r6625  
    10791079    <p>Cc myself: <input type="checkbox" name="cc_myself" /></p> 
    10801080 
     1081``error_messages`` 
     1082~~~~~~~~~~~~~~~~~~ 
     1083 
     1084**New in Django development version** 
     1085 
     1086The ``error_messages`` argument lets you override the default messages which the 
     1087field will raise. Pass in a dictionary with keys matching the error messages you 
     1088want to override. For example:: 
     1089 
     1090    >>> generic = forms.CharField() 
     1091    >>> generic.clean('') 
     1092    Traceback (most recent call last): 
     1093      ... 
     1094    ValidationError: [u'This field is required.'] 
     1095 
     1096    >>> name = forms.CharField(error_messages={'required': 'Please enter your name'}) 
     1097    >>> name.clean('') 
     1098    Traceback (most recent call last): 
     1099      ... 
     1100    ValidationError: [u'Please enter your name'] 
     1101 
     1102In the `built-in Field classes`_ section below, each Field defines the error 
     1103message keys it uses.   
     1104 
    10811105Dynamic initial values 
    10821106---------------------- 
     
    11441168    * Validates that the check box is checked (i.e. the value is ``True``) if 
    11451169      the field has ``required=True``. 
     1170    * Error message keys: ``required`` 
    11461171 
    11471172**New in Django development version:** The empty value for a ``CheckboxInput`` 
     
    11631188    * Validates ``max_length`` or ``min_length``, if they are provided. 
    11641189      Otherwise, all inputs are valid. 
     1190    * Error message keys: ``required``, ``max_length``, ``min_length`` 
    11651191 
    11661192Has two optional arguments for validation, ``max_length`` and ``min_length``. 
     
    11751201    * Normalizes to: A Unicode object. 
    11761202    * Validates that the given value exists in the list of choices. 
     1203    * Error message keys: ``required``, ``invalid_choice`` 
    11771204 
    11781205Takes one extra argument, ``choices``, which is an iterable (e.g., a list or 
     
    11871214    * Validates that the given value is either a ``datetime.date``, 
    11881215      ``datetime.datetime`` or string formatted in a particular date format. 
     1216    * Error message keys: ``required``, ``invalid`` 
    11891217 
    11901218Takes one optional argument, ``input_formats``, which is a list of formats used 
     
    12071235    * Validates that the given value is either a ``datetime.datetime``, 
    12081236      ``datetime.date`` or string formatted in a particular datetime format. 
     1237    * Error message keys: ``required``, ``invalid`` 
    12091238 
    12101239Takes one optional argument, ``input_formats``, which is a list of formats used 
     
    12361265    * Validates that the given value is a decimal. Leading and trailing 
    12371266      whitespace is ignored. 
     1267    * Error message keys: ``required``, ``invalid``, ``max_value``, 
     1268      ``min_value``, ``max_digits``, ``max_decimal_places``, 
     1269      ``max_whole_digits`` 
    12381270 
    12391271Takes four optional arguments: ``max_value``, ``min_value``, ``max_digits``, 
     
    12521284    * Validates that the given value is a valid e-mail address, using a 
    12531285      moderately complex regular expression. 
     1286    * Error message keys: ``required``, ``invalid`` 
    12541287 
    12551288Has two optional arguments for validation, ``max_length`` and ``min_length``. 
     
    12671300      and file name into a single object. 
    12681301    * Validates that non-empty file data has been bound to the form. 
     1302    * Error message keys: ``required``, ``invalid``, ``missing``, ``empty`` 
    12691303 
    12701304An ``UploadedFile`` object has two attributes: 
     
    12971331    * Validates that file data has been bound to the form, and that the 
    12981332      file is of an image format understood by PIL. 
     1333    * Error message keys: ``required``, ``invalid``, ``missing``, ``empty``, 
     1334      ``invalid_image`` 
    12991335 
    13001336Using an ImageField requires that the `Python Imaging Library`_ is installed. 
     
    13131349    * Validates that the given value is an integer. Leading and trailing 
    13141350      whitespace is allowed, as in Python's ``int()`` function. 
     1351    * Error message keys: ``required``, ``invalid``, ``max_value``, 
     1352      ``min_value`` 
    13151353 
    13161354Takes two optional arguments for validation, ``max_value`` and ``min_value``. 
     
    13251363    * Validates that the given value is a valid IPv4 address, using a regular 
    13261364      expression. 
     1365    * Error message keys: ``required``, ``invalid`` 
    13271366 
    13281367``MultipleChoiceField`` 
     
    13341373    * Validates that every value in the given list of values exists in the list 
    13351374      of choices. 
     1375    * Error message keys: ``required``, ``invalid_choice``, ``invalid_list`` 
    13361376 
    13371377Takes one extra argument, ``choices``, which is an iterable (e.g., a list or 
     
    13541394    * Validates that the given value matches against a certain regular 
    13551395      expression. 
     1396    * Error message keys: ``required``, ``invalid`` 
    13561397 
    13571398Takes one required argument, ``regex``, which is a regular expression specified 
     
    13651406    ``max_length``          Ensures the string has at most this many characters. 
    13661407    ``min_length``          Ensures the string has at least this many characters. 
    1367     ``error_message``       Error message to return for failed validation. If no 
    1368                             message is provided, a generic error message will be 
    1369                             used. 
    13701408    ======================  ===================================================== 
     1409 
     1410The optional argument ``error_message`` is also accepted for backwards 
     1411compatibility. The preferred way to provide an error message is to use the 
     1412``error_messages`` argument, passing a dictionary with ``'invalid'`` as a key 
     1413and the error message as the value.  
    13711414 
    13721415``TimeField`` 
     
    13781421    * Validates that the given value is either a ``datetime.time`` or string 
    13791422      formatted in a particular time format. 
     1423    * Error message keys: ``required``, ``invalid`` 
    13801424 
    13811425Takes one optional argument, ``input_formats``, which is a list of formats used 
     
    13941438    * Normalizes to: A Unicode object. 
    13951439    * Validates that the given value is a valid URL. 
     1440    * Error message keys: ``required``, ``invalid``, ``invalid_link`` 
    13961441 
    13971442Takes the following optional arguments: 
  • django/trunk/tests/regressiontests/forms/tests.py

    r6555 r6625  
    33from fields import tests as fields_tests 
    44from forms import tests as form_tests 
     5from error_messages import tests as custom_error_message_tests 
    56from localflavor.ar import tests as localflavor_ar_tests 
    67from localflavor.au import tests as localflavor_au_tests 
     
    3031    'fields_tests': fields_tests, 
    3132    'form_tests': form_tests, 
     33    'custom_error_message_tests': custom_error_message_tests, 
    3234    'localflavor_ar_tests': localflavor_ar_tests, 
    3335    'localflavor_au_tests': localflavor_au_tests, 
  • django/trunk/tests/regressiontests/forms/util.py

    r6379 r6625  
    4343>>> print ValidationError(["First error.", u"Not \u03C0.", ugettext_lazy("Error.")]).messages 
    4444<ul class="errorlist"><li>First error.</li><li>Not π.</li><li>Error.</li></ul> 
     45 
     46>>> class VeryBadError: 
     47...     def __unicode__(self): return u"A very bad error." 
     48 
     49# Can take a non-string. 
     50>>> print ValidationError(VeryBadError()).messages 
     51<ul class="errorlist"><li>A very bad error.</li></ul> 
    4552"""