Changeset 6625
- Timestamp:
- 10/28/07 00:40:26 (10 months ago)
- Files:
-
- django/trunk/django/newforms/fields.py (modified) (36 diffs)
- django/trunk/django/newforms/util.py (modified) (2 diffs)
- django/trunk/django/test/testcases.py (modified) (1 diff)
- django/trunk/docs/newforms.txt (modified) (17 diffs)
- django/trunk/tests/regressiontests/forms/error_messages.py (added)
- django/trunk/tests/regressiontests/forms/tests.py (modified) (2 diffs)
- django/trunk/tests/regressiontests/forms/util.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/trunk/django/newforms/fields.py
r6623 r6625 17 17 from sets import Set as set 18 18 19 from django.utils.translation import ugettext 19 from django.utils.translation import ugettext_lazy 20 20 from django.utils.encoding import StrAndUnicode, smart_unicode 21 21 … … 42 42 widget = TextInput # Default widget to use when rendering this type of Field. 43 43 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 } 44 48 45 49 # Tracks each time a Field instance is created. Used to retain order. 46 50 creation_counter = 0 47 51 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): 49 54 # required -- Boolean that specifies whether the field is required. 50 55 # True by default. … … 79 84 Field.creation_counter += 1 80 85 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 81 100 def clean(self, value): 82 101 """ … … 87 106 """ 88 107 if self.required and value in EMPTY_VALUES: 89 raise ValidationError( ugettext(u'This field is required.'))108 raise ValidationError(self.error_messages['required']) 90 109 return value 91 110 … … 105 124 106 125 class 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 107 131 def __init__(self, max_length=None, min_length=None, *args, **kwargs): 108 132 self.max_length, self.min_length = max_length, min_length … … 117 141 value_length = len(value) 118 142 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}) 120 144 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}) 122 146 return value 123 147 … … 128 152 129 153 class 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 130 160 def __init__(self, max_value=None, min_value=None, *args, **kwargs): 131 161 self.max_value, self.min_value = max_value, min_value … … 143 173 value = int(str(value)) 144 174 except (ValueError, TypeError): 145 raise ValidationError( ugettext(u'Enter a whole number.'))175 raise ValidationError(self.error_messages['invalid']) 146 176 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) 148 178 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) 150 180 return value 151 181 152 182 class 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 153 189 def __init__(self, max_value=None, min_value=None, *args, **kwargs): 154 190 self.max_value, self.min_value = max_value, min_value … … 166 202 value = float(value) 167 203 except (ValueError, TypeError): 168 raise ValidationError( ugettext('Enter a number.'))204 raise ValidationError(self.error_messages['invalid']) 169 205 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) 171 207 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) 173 209 return value 174 210 175 211 class 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 176 221 def __init__(self, max_value=None, min_value=None, max_digits=None, decimal_places=None, *args, **kwargs): 177 222 self.max_value, self.min_value = max_value, min_value … … 193 238 value = Decimal(value) 194 239 except DecimalException: 195 raise ValidationError( ugettext('Enter a number.'))240 raise ValidationError(self.error_messages['invalid']) 196 241 pieces = str(value).lstrip("-").split('.') 197 242 decimals = (len(pieces) == 2) and len(pieces[1]) or 0 198 243 digits = len(pieces[0]) 199 244 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) 201 246 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) 203 248 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) 205 250 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) 207 252 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)) 209 254 return value 210 255 … … 218 263 219 264 class DateField(Field): 265 default_error_messages = { 266 'invalid': ugettext_lazy(u'Enter a valid date.'), 267 } 268 220 269 def __init__(self, input_formats=None, *args, **kwargs): 221 270 super(DateField, self).__init__(*args, **kwargs) … … 239 288 except ValueError: 240 289 continue 241 raise ValidationError( ugettext(u'Enter a valid date.'))290 raise ValidationError(self.error_messages['invalid']) 242 291 243 292 DEFAULT_TIME_INPUT_FORMATS = ( … … 247 296 248 297 class TimeField(Field): 298 default_error_messages = { 299 'invalid': ugettext_lazy(u'Enter a valid time.') 300 } 301 249 302 def __init__(self, input_formats=None, *args, **kwargs): 250 303 super(TimeField, self).__init__(*args, **kwargs) … … 266 319 except ValueError: 267 320 continue 268 raise ValidationError( ugettext(u'Enter a valid time.'))321 raise ValidationError(self.error_messages['invalid']) 269 322 270 323 DEFAULT_DATETIME_INPUT_FORMATS = ( … … 282 335 class DateTimeField(Field): 283 336 widget = DateTimeInput 337 default_error_messages = { 338 'invalid': ugettext_lazy(u'Enter a valid date/time.'), 339 } 284 340 285 341 def __init__(self, input_formats=None, *args, **kwargs): … … 303 359 # components: date and time. 304 360 if len(value) != 2: 305 raise ValidationError( ugettext(u'Enter a valid date/time.'))361 raise ValidationError(self.error_messages['invalid']) 306 362 value = '%s %s' % tuple(value) 307 363 for format in self.input_formats: … … 310 366 except ValueError: 311 367 continue 312 raise ValidationError( ugettext(u'Enter a valid date/time.'))368 raise ValidationError(self.error_messages['invalid']) 313 369 314 370 class RegexField(CharField): … … 319 375 'Enter a valid value' is too generic for you. 320 376 """ 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 321 382 super(RegexField, self).__init__(max_length, min_length, *args, **kwargs) 322 383 if isinstance(regex, basestring): 323 384 regex = re.compile(regex) 324 385 self.regex = regex 325 self.error_message = error_message or ugettext(u'Enter a valid value.')326 386 327 387 def clean(self, value): … … 334 394 return value 335 395 if not self.regex.search(value): 336 raise ValidationError(self.error_message )396 raise ValidationError(self.error_messages['invalid']) 337 397 return value 338 398 … … 343 403 344 404 class EmailField(RegexField): 405 default_error_messages = { 406 'invalid': ugettext_lazy(u'Enter a valid e-mail address.'), 407 } 408 345 409 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) 348 412 349 413 try: … … 369 433 class FileField(Field): 370 434 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 371 441 def __init__(self, *args, **kwargs): 372 442 super(FileField, self).__init__(*args, **kwargs) … … 379 449 f = UploadedFile(data['filename'], data['content']) 380 450 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']) 382 452 except KeyError: 383 raise ValidationError( ugettext(u"No file was submitted."))453 raise ValidationError(self.error_messages['missing']) 384 454 if not f.content: 385 raise ValidationError( ugettext(u"The submitted file is empty."))455 raise ValidationError(self.error_messages['empty']) 386 456 return f 387 457 388 458 class 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 389 463 def clean(self, data): 390 464 """ … … 407 481 trial_image.verify() 408 482 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']) 410 484 return f 411 485 … … 419 493 420 494 class 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 421 500 def __init__(self, max_length=None, min_length=None, verify_exists=False, 422 501 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) 424 504 self.verify_exists = verify_exists 425 505 self.user_agent = validator_user_agent … … 446 526 u = urllib2.urlopen(req) 447 527 except ValueError: 448 raise ValidationError( ugettext(u'Enter a valid URL.'))528 raise ValidationError(self.error_messages['invalid']) 449 529 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']) 451 531 return value 452 532 … … 475 555 class ChoiceField(Field): 476 556 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) 480 565 self.choices = choices 481 566 … … 503 588 valid_values = set([smart_unicode(k) for k, v in self.choices]) 504 589 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}) 506 591 return value 507 592 … … 509 594 hidden_widget = MultipleHiddenInput 510 595 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 } 511 600 512 601 def clean(self, value): … … 515 604 """ 516 605 if self.required and not value: 517 raise ValidationError( ugettext(u'This field is required.'))606 raise ValidationError(self.error_messages['required']) 518 607 elif not self.required and not value: 519 608 return [] 520 609 if not isinstance(value, (list, tuple)): 521 raise ValidationError( ugettext(u'Enter a list of values.'))610 raise ValidationError(self.error_messages['invalid_list']) 522 611 new_value = [smart_unicode(val) for val in value] 523 612 # Validate that each value in the value list is in self.choices. … … 525 614 for val in new_value: 526 615 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}) 528 617 return new_value 529 618 … … 568 657 You'll probably want to use this with MultiWidget. 569 658 """ 659 default_error_messages = { 660 'invalid': ugettext_lazy(u'Enter a list of values.'), 661 } 662 570 663 def __init__(self, fields=(), *args, **kwargs): 571 664 super(MultiValueField, self).__init__(*args, **kwargs) … … 591 684 if not value or not [v for v in value if v not in EMPTY_VALUES]: 592 685 if self.required: 593 raise ValidationError( ugettext(u'This field is required.'))686 raise ValidationError(self.error_messages['required']) 594 687 else: 595 688 return self.compress([]) 596 689 else: 597 raise ValidationError( ugettext(u'Enter a list of values.'))690 raise ValidationError(self.error_messages['invalid']) 598 691 for i, field in enumerate(self.fields): 599 692 try: … … 602 695 field_value = None 603 696 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']) 605 698 try: 606 699 clean_data.append(field.clean(field_value)) … … 626 719 627 720 class 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 628 726 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 ) 630 734 super(SplitDateTimeField, self).__init__(fields, *args, **kwargs) 631 735 … … 635 739 # (possible if SplitDateTimeField has required=False). 636 740 if data_list[0] in EMPTY_VALUES: 637 raise ValidationError( ugettext(u'Enter a valid date.'))741 raise ValidationError(self.error_messages['invalid_date']) 638 742 if data_list[1] in EMPTY_VALUES: 639 raise ValidationError( ugettext(u'Enter a valid time.'))743 raise ValidationError(self.error_messages['invalid_time']) 640 744 return datetime.datetime.combine(*data_list) 641 745 return None … … 644 748 645 749 class IPAddressField(RegexField): 750 default_error_messages = { 751 'invalid': ugettext_lazy(u'Enter a valid IPv4 address.'), 752 } 753 646 754 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 43 43 return u'\n'.join([u'* %s' % force_unicode(e) for e in self]) 44 44 45 def __repr__(self): 46 return repr([force_unicode(e) for e in self]) 47 45 48 class ValidationError(Exception): 46 49 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 """ 48 54 if isinstance(message, list): 49 55 self.messages = ErrorList([smart_unicode(msg) for msg in message]) 50 56 else: 51 assert isinstance(message, (basestring, Promise)), ("%s should be a basestring or lazy translation" % repr(message))52 57 message = smart_unicode(message) 53 58 self.messages = ErrorList([message]) … … 59 64 # See http://www.python.org/doc/current/tut/node10.html#handling 60 65 return repr(self.messages) 61 django/trunk/django/test/testcases.py
r6164 r6625 147 147 " error '%s' (actual errors: %s)" % 148 148 (field, form, i, err, 149 list(field_errors)))149 repr(field_errors))) 150 150 elif field in context[form].fields: 151 151 self.fail("The field '%s' on form '%s' in context %d" django/trunk/docs/newforms.txt
r6578 r6625 1079 1079 <p>Cc myself: <input type="checkbox" name="cc_myself" /></p> 1080 1080 1081 ``error_messages`` 1082 ~~~~~~~~~~~~~~~~~~ 1083 1084 **New in Django development version** 1085 1086 The ``error_messages`` argument lets you override the default messages which the 1087 field will raise. Pass in a dictionary with keys matching the error messages you 1088 want 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 1102 In the `built-in Field classes`_ section below, each Field defines the error 1103 message keys it uses. 1104 1081 1105 Dynamic initial values 1082 1106 ---------------------- … … 1144 1168 * Validates that the check box is checked (i.e. the value is ``True``) if 1145 1169 the field has ``required=True``. 1170 * Error message keys: ``required`` 1146 1171 1147 1172 **New in Django development version:** The empty value for a ``CheckboxInput`` … … 1163 1188 * Validates ``max_length`` or ``min_length``, if they are provided. 1164 1189 Otherwise, all inputs are valid. 1190 * Error message keys: ``required``, ``max_length``, ``min_length`` 1165 1191 1166 1192 Has two optional arguments for validation, ``max_length`` and ``min_length``. … … 1175 1201 * Normalizes to: A Unicode object. 1176 1202 * Validates that the given value exists in the list of choices. 1203 * Error message keys: ``required``, ``invalid_choice`` 1177 1204 1178 1205 Takes one extra argument, ``choices``, which is an iterable (e.g., a list or … … 1187 1214 * Validates that the given value is either a ``datetime.date``, 1188 1215 ``datetime.datetime`` or string formatted in a particular date format. 1216 * Error message keys: ``required``, ``invalid`` 1189 1217 1190 1218 Takes one optional argument, ``input_formats``, which is a list of formats used … … 1207 1235 * Validates that the given value is either a ``datetime.datetime``, 1208 1236 ``datetime.date`` or string formatted in a particular datetime format. 1237 * Error message keys: ``required``, ``invalid`` 1209 1238 1210 1239 Takes one optional argument, ``input_formats``, which is a list of formats used … … 1236 1265 * Validates that the given value is a decimal. Leading and trailing 1237 1266 whitespace is ignored. 1267 * Error message keys: ``required``, ``invalid``, ``max_value``, 1268 ``min_value``, ``max_digits``, ``max_decimal_places``, 1269 ``max_whole_digits`` 1238 1270 1239 1271 Takes four optional arguments: ``max_value``, ``min_value``, ``max_digits``, … … 1252 1284 * Validates that the given value is a valid e-mail address, using a 1253 1285 moderately complex regular expression. 1286 * Error message keys: ``required``, ``invalid`` 1254 1287 1255 1288 Has two optional arguments for validation, ``max_length`` and ``min_length``. … … 1267 1300 and file name into a single object. 1268 1301 * Validates that non-empty file data has been bound to the form. 1302 * Error message keys: ``required``, ``invalid``, ``missing``, ``empty`` 1269 1303 1270 1304 An ``UploadedFile`` object has two attributes: … … 1297 1331 * Validates that file data has been bound to the form, and that the 1298 1332 file is of an image format understood by PIL. 1333 * Error message keys: ``required``, ``invalid``, ``missing``, ``empty``, 1334 ``invalid_image`` 1299 1335 1300 1336 Using an ImageField requires that the `Python Imaging Library`_ is installed. … … 1313 1349 * Validates that the given value is an integer. Leading and trailing 1314 1350 whitespace is allowed, as in Python's ``int()`` function. 1351 * Error message keys: ``required``, ``invalid``, ``max_value``, 1352 ``min_value`` 1315 1353 1316 1354 Takes two optional arguments for validation, ``max_value`` and ``min_value``. … … 1325 1363 * Validates that the given value is a valid IPv4 address, using a regular 1326 1364 expression. 1365 * Error message keys: ``required``, ``invalid`` 1327 1366 1328 1367 ``MultipleChoiceField`` … … 1334 1373 * Validates that every value in the given list of values exists in the list 1335 1374 of choices. 1375 * Error message keys: ``required``, ``invalid_choice``, ``invalid_list`` 1336 1376 1337 1377 Takes one extra argument, ``choices``, which is an iterable (e.g., a list or … … 1354 1394 * Validates that the given value matches against a certain regular 1355 1395 expression. 1396 * Error message keys: ``required``, ``invalid`` 1356 1397 1357 1398 Takes one required argument, ``regex``, which is a regular expression specified … … 1365 1406 ``max_length`` Ensures the string has at most this many characters. 1366 1407 ``min_length`` Ensures the string has at least this many characters. 1367 ``error_message`` Error message to return for failed validation. If no1368 message is provided, a generic error message will be1369 used.1370 1408 ====================== ===================================================== 1409 1410 The optional argument ``error_message`` is also accepted for backwards 1411 compatibility. The preferred way to provide an error message is to use the 1412 ``error_messages`` argument, passing a dictionary with ``'invalid'`` as a key 1413 and the error message as the value. 1371 1414 1372 1415 ``TimeField`` … … 1378 1421 * Validates that the given value is either a ``datetime.time`` or string 1379 1422 formatted in a particular time format. 1423 * Error message keys: ``required``, ``invalid`` 1380 1424 1381 1425 Takes one optional argument, ``input_formats``, which is a list of formats used … … 1394 1438 * Normalizes to: A Unicode object. 1395 1439 * Validates that the given value is a valid URL. 1440 * Error message keys: ``required``, ``invalid``, ``invalid_link`` 1396 1441 1397 1442 Takes the following optional arguments: django/trunk/tests/regressiontests/forms/tests.py
r6555 r6625 3 3 from fields import tests as fields_tests 4 4 from forms import tests as form_tests 5 from error_messages import tests as custom_error_message_tests 5 6 from localflavor.ar import tests as localflavor_ar_tests 6 7 from localflavor.au import tests as localflavor_au_tests … … 30 31 'fields_tests': fields_tests, 31 32 'form_tests': form_tests, 33 'custom_error_message_tests': custom_error_message_tests, 32 34 'localflavor_ar_tests': localflavor_ar_tests, 33 35 'localflavor_au_tests': localflavor_au_tests, django/trunk/tests/regressiontests/forms/util.py
r6379 r6625 43 43 >>> print ValidationError(["First error.", u"Not \u03C0.", ugettext_lazy("Error.")]).messages 44 44 <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> 45 52 """
