Ticket #3457: newforms_error_messages.4.patch
File newforms_error_messages.4.patch, 42.7 KB (added by , 17 years ago) |
---|
-
django/test/testcases.py
8 8 from django.core.management import call_command 9 9 from django.test import _doctest as doctest 10 10 from django.test.client import Client 11 from django.utils.encoding import force_unicode 11 12 12 13 normalize_long_ints = lambda s: re.sub(r'(?<![\w])(\d+)L(?![\w])', '\\1', s) 13 14 … … 140 141 for err in errors: 141 142 if field: 142 143 if field in context[form].errors: 144 #field_errors = [force_unicode(error) for error 145 # in context[form].errors[field]] 143 146 field_errors = context[form].errors[field] 144 147 self.failUnless(err in field_errors, 145 "The field '%s' on form '%s' in"146 " context %d does not contain the"147 " error '%s' (actual errors: %s)" %148 u"The field '%s' on form '%s' in" 149 u" context %d does not contain the" 150 u" error '%s' (actual errors: %s)" % 148 151 (field, form, i, err, 149 152 list(field_errors))) 150 153 elif field in context[form].fields: -
django/newforms/util.py
1 1 from django.utils.html import escape 2 from django.utils.encoding import smart_unicode, StrAndUnicode2 from django.utils.encoding import smart_unicode, force_unicode, StrAndUnicode 3 3 from django.utils.functional import Promise 4 4 5 5 def flatatt(attrs): … … 42 42 if not self: return u'' 43 43 return u'\n'.join([u'* %s' % smart_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 50 "ValidationError can be passed a string or a list." 48 51 if isinstance(message, list): 49 52 self.messages = ErrorList([smart_unicode(msg) for msg in message]) 50 53 else: 51 assert isinstance(message, (basestring, Promise)), ("%s should be a basestring or lazy translation" % repr(message))52 54 message = smart_unicode(message) 53 55 self.messages = ErrorList([message]) 54 56 -
django/newforms/fields.py
7 7 import re 8 8 import time 9 9 10 from django.utils.translation import ugettext 10 from django.utils.translation import ugettext_lazy 11 11 from django.utils.encoding import StrAndUnicode, smart_unicode 12 12 13 13 from util import ErrorList, ValidationError … … 45 45 class Field(object): 46 46 widget = TextInput # Default widget to use when rendering this type of Field. 47 47 hidden_widget = HiddenInput # Default widget to use when rendering this as "hidden". 48 default_error_messages = { 49 'required': ugettext_lazy(u'This field is required.'), 50 'invalid': ugettext_lazy(u'Enter a valid value.'), 51 } 48 52 49 53 # Tracks each time a Field instance is created. Used to retain order. 50 54 creation_counter = 0 51 55 52 def __init__(self, required=True, widget=None, label=None, initial=None, help_text=None): 56 def __init__(self, required=True, widget=None, label=None, initial=None, 57 help_text=None, error_messages=None): 53 58 # required -- Boolean that specifies whether the field is required. 54 59 # True by default. 55 60 # widget -- A Widget class, or instance of a Widget class, that should … … 82 87 self.creation_counter = Field.creation_counter 83 88 Field.creation_counter += 1 84 89 90 self.error_messages = self._build_error_messages(error_messages) 91 92 def _build_error_messages(self, extra_error_messages): 93 error_messages = {} 94 def get_default_error_messages(klass): 95 for base_class in klass.__bases__: 96 get_default_error_messages(base_class) 97 if hasattr(klass, 'default_error_messages'): 98 error_messages.update(klass.default_error_messages) 99 get_default_error_messages(self.__class__) 100 if extra_error_messages: 101 error_messages.update(extra_error_messages) 102 return error_messages 103 85 104 def clean(self, value): 86 105 """ 87 106 Validates the given value and returns its "cleaned" value as an … … 90 109 Raises ValidationError for any errors. 91 110 """ 92 111 if self.required and value in EMPTY_VALUES: 93 raise ValidationError( ugettext(u'This field is required.'))112 raise ValidationError(self.error_messages['required']) 94 113 return value 95 114 96 115 def widget_attrs(self, widget): … … 108 127 return result 109 128 110 129 class CharField(Field): 130 default_error_messages = { 131 'max_length': ugettext_lazy(u'Ensure this value has at most %(max)d characters (it has %(length)d).'), 132 'min_length': ugettext_lazy(u'Ensure this value has at least %(min)d characters (it has %(length)d).'), 133 } 134 111 135 def __init__(self, max_length=None, min_length=None, *args, **kwargs): 112 136 self.max_length, self.min_length = max_length, min_length 113 137 super(CharField, self).__init__(*args, **kwargs) … … 120 144 value = smart_unicode(value) 121 145 value_length = len(value) 122 146 if self.max_length is not None and value_length > self.max_length: 123 raise ValidationError( ugettext(u'Ensure this value has at most %(max)d characters (it has %(length)d).')% {'max': self.max_length, 'length': value_length})147 raise ValidationError(self.error_messages['max_length'] % {'max': self.max_length, 'length': value_length}) 124 148 if self.min_length is not None and value_length < self.min_length: 125 raise ValidationError( ugettext(u'Ensure this value has at least %(min)d characters (it has %(length)d).')% {'min': self.min_length, 'length': value_length})149 raise ValidationError(self.error_messages['min_length'] % {'min': self.min_length, 'length': value_length}) 126 150 return value 127 151 128 152 def widget_attrs(self, widget): … … 131 155 return {'maxlength': str(self.max_length)} 132 156 133 157 class IntegerField(Field): 158 default_error_messages = { 159 'invalid': ugettext_lazy(u'Enter a whole number.'), 160 'max_value': ugettext_lazy(u'Ensure this value is less than or equal to %s.'), 161 'min_value': ugettext_lazy(u'Ensure this value is greater than or equal to %s.'), 162 } 163 134 164 def __init__(self, max_value=None, min_value=None, *args, **kwargs): 135 165 self.max_value, self.min_value = max_value, min_value 136 166 super(IntegerField, self).__init__(*args, **kwargs) … … 146 176 try: 147 177 value = int(value) 148 178 except (ValueError, TypeError): 149 raise ValidationError( ugettext(u'Enter a whole number.'))179 raise ValidationError(self.error_messages['invalid']) 150 180 if self.max_value is not None and value > self.max_value: 151 raise ValidationError( ugettext(u'Ensure this value is less than or equal to %s.')% self.max_value)181 raise ValidationError(self.error_messages['max_value'] % self.max_value) 152 182 if self.min_value is not None and value < self.min_value: 153 raise ValidationError( ugettext(u'Ensure this value is greater than or equal to %s.')% self.min_value)183 raise ValidationError(self.error_messages['min_value'] % self.min_value) 154 184 return value 155 185 156 186 class FloatField(Field): 187 default_error_messages = { 188 'invalid': ugettext_lazy(u'Enter a number.'), 189 'max_value': ugettext_lazy(u'Ensure this value is less than or equal to %s.'), 190 'min_value': ugettext_lazy(u'Ensure this value is greater than or equal to %s.'), 191 } 192 157 193 def __init__(self, max_value=None, min_value=None, *args, **kwargs): 158 194 self.max_value, self.min_value = max_value, min_value 159 195 Field.__init__(self, *args, **kwargs) … … 169 205 try: 170 206 value = float(value) 171 207 except (ValueError, TypeError): 172 raise ValidationError( ugettext('Enter a number.'))208 raise ValidationError(self.error_messages['invalid']) 173 209 if self.max_value is not None and value > self.max_value: 174 raise ValidationError( ugettext('Ensure this value is less than or equal to %s.')% self.max_value)210 raise ValidationError(self.error_messages['max_value'] % self.max_value) 175 211 if self.min_value is not None and value < self.min_value: 176 raise ValidationError( ugettext('Ensure this value is greater than or equal to %s.')% self.min_value)212 raise ValidationError(self.error_messages['min_value'] % self.min_value) 177 213 return value 178 214 179 215 class DecimalField(Field): 216 default_error_messages = { 217 'invalid': ugettext_lazy(u'Enter a number.'), 218 'max_value': ugettext_lazy(u'Ensure this value is less than or equal to %s.'), 219 'min_value': ugettext_lazy(u'Ensure this value is greater than or equal to %s.'), 220 'max_digits': ugettext_lazy('Ensure that there are no more than %s digits in total.'), 221 'max_decimal_places': ugettext_lazy('Ensure that there are no more than %s decimal places.'), 222 'max_whole_digits': ugettext_lazy('Ensure that there are no more than %s digits before the decimal point.') 223 } 224 180 225 def __init__(self, max_value=None, min_value=None, max_digits=None, decimal_places=None, *args, **kwargs): 181 226 self.max_value, self.min_value = max_value, min_value 182 227 self.max_digits, self.decimal_places = max_digits, decimal_places … … 196 241 try: 197 242 value = Decimal(value) 198 243 except DecimalException: 199 raise ValidationError( ugettext('Enter a number.'))244 raise ValidationError(self.error_messages['invalid']) 200 245 pieces = str(value).lstrip("-").split('.') 201 246 decimals = (len(pieces) == 2) and len(pieces[1]) or 0 202 247 digits = len(pieces[0]) 203 248 if self.max_value is not None and value > self.max_value: 204 raise ValidationError( ugettext('Ensure this value is less than or equal to %s.')% self.max_value)249 raise ValidationError(self.error_messages['max_value'] % self.max_value) 205 250 if self.min_value is not None and value < self.min_value: 206 raise ValidationError( ugettext('Ensure this value is greater than or equal to %s.')% self.min_value)251 raise ValidationError(self.error_messages['min_value'] % self.min_value) 207 252 if self.max_digits is not None and (digits + decimals) > self.max_digits: 208 raise ValidationError( ugettext('Ensure that there are no more than %s digits in total.')% self.max_digits)253 raise ValidationError(self.error_messages['max_digits'] % self.max_digits) 209 254 if self.decimal_places is not None and decimals > self.decimal_places: 210 raise ValidationError( ugettext('Ensure that there are no more than %s decimal places.')% self.decimal_places)255 raise ValidationError(self.error_messages['max_decimal_places'] % self.decimal_places) 211 256 if self.max_digits is not None and self.decimal_places is not None and digits > (self.max_digits - self.decimal_places): 212 raise ValidationError( ugettext('Ensure that there are no more than %s digits before the decimal point.')% (self.max_digits - self.decimal_places))257 raise ValidationError(self.error_messages['max_whole_digits'] % (self.max_digits - self.decimal_places)) 213 258 return value 214 259 215 260 DEFAULT_DATE_INPUT_FORMATS = ( … … 221 266 ) 222 267 223 268 class DateField(Field): 269 default_error_messages = { 270 'invalid': ugettext_lazy(u'Enter a valid date.'), 271 } 272 224 273 def __init__(self, input_formats=None, *args, **kwargs): 225 274 super(DateField, self).__init__(*args, **kwargs) 226 275 self.input_formats = input_formats or DEFAULT_DATE_INPUT_FORMATS … … 242 291 return datetime.date(*time.strptime(value, format)[:3]) 243 292 except ValueError: 244 293 continue 245 raise ValidationError( ugettext(u'Enter a valid date.'))294 raise ValidationError(self.error_messages['invalid']) 246 295 247 296 DEFAULT_TIME_INPUT_FORMATS = ( 248 297 '%H:%M:%S', # '14:30:59' … … 250 299 ) 251 300 252 301 class TimeField(Field): 302 default_error_messages = { 303 'invalid': ugettext_lazy(u'Enter a valid time.') 304 } 305 253 306 def __init__(self, input_formats=None, *args, **kwargs): 254 307 super(TimeField, self).__init__(*args, **kwargs) 255 308 self.input_formats = input_formats or DEFAULT_TIME_INPUT_FORMATS … … 269 322 return datetime.time(*time.strptime(value, format)[3:6]) 270 323 except ValueError: 271 324 continue 272 raise ValidationError( ugettext(u'Enter a valid time.'))325 raise ValidationError(self.error_messages['invalid']) 273 326 274 327 DEFAULT_DATETIME_INPUT_FORMATS = ( 275 328 '%Y-%m-%d %H:%M:%S', # '2006-10-25 14:30:59' … … 284 337 ) 285 338 286 339 class DateTimeField(Field): 340 default_error_messages = { 341 'invalid': ugettext_lazy(u'Enter a valid date/time.'), 342 } 343 287 344 def __init__(self, input_formats=None, *args, **kwargs): 288 345 super(DateTimeField, self).__init__(*args, **kwargs) 289 346 self.input_formats = input_formats or DEFAULT_DATETIME_INPUT_FORMATS … … 305 362 return datetime.datetime(*time.strptime(value, format)[:6]) 306 363 except ValueError: 307 364 continue 308 raise ValidationError( ugettext(u'Enter a valid date/time.'))365 raise ValidationError(self.error_messages['invalid']) 309 366 310 367 class RegexField(CharField): 311 368 def __init__(self, regex, max_length=None, min_length=None, error_message=None, *args, **kwargs): … … 314 371 error_message is an optional error message to use, if 315 372 'Enter a valid value' is too generic for you. 316 373 """ 374 # error_message is just kept for backwards compatibility: 375 if error_message: 376 error_messages = kwargs.get('error_messages') or {} 377 error_messages['invalid'] = error_message 378 kwargs['error_messages'] = error_messages 317 379 super(RegexField, self).__init__(max_length, min_length, *args, **kwargs) 318 380 if isinstance(regex, basestring): 319 381 regex = re.compile(regex) 320 382 self.regex = regex 321 self.error_message = error_message or ugettext(u'Enter a valid value.')322 383 323 384 def clean(self, value): 324 385 """ … … 329 390 if value == u'': 330 391 return value 331 392 if not self.regex.search(value): 332 raise ValidationError(self.error_message )393 raise ValidationError(self.error_messages['invalid']) 333 394 return value 334 395 335 396 email_re = re.compile( … … 338 399 r')@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$', re.IGNORECASE) # domain 339 400 340 401 class EmailField(RegexField): 402 default_error_messages = { 403 'invalid': ugettext_lazy(u'Enter a valid e-mail address.'), 404 } 405 341 406 def __init__(self, max_length=None, min_length=None, *args, **kwargs): 342 RegexField.__init__(self, email_re, max_length, min_length, 343 ugettext(u'Enter a valid e-mail address.'), *args,**kwargs)407 RegexField.__init__(self, email_re, max_length, min_length, *args, 408 **kwargs) 344 409 345 410 try: 346 411 from django.conf import settings … … 364 429 365 430 class FileField(Field): 366 431 widget = FileInput 432 default_error_messages = { 433 'invalid': ugettext_lazy(u"No file was submitted. Check the encoding type on the form."), 434 'missing': ugettext_lazy(u"No file was submitted."), 435 'empty': ugettext_lazy(u"The submitted file is empty."), 436 } 437 367 438 def __init__(self, *args, **kwargs): 368 439 super(FileField, self).__init__(*args, **kwargs) 369 440 … … 374 445 try: 375 446 f = UploadedFile(data['filename'], data['content']) 376 447 except TypeError: 377 raise ValidationError( ugettext(u"No file was submitted. Check the encoding type on the form."))448 raise ValidationError(self.error_messages['invalid']) 378 449 except KeyError: 379 raise ValidationError( ugettext(u"No file was submitted."))450 raise ValidationError(self.error_messages['missing']) 380 451 if not f.content: 381 raise ValidationError( ugettext(u"The submitted file is empty."))452 raise ValidationError(self.error_messages['empty']) 382 453 return f 383 454 384 455 class ImageField(FileField): 456 default_error_messages = { 457 'invalid_image': ugettext_lazy(u"Upload a valid image. The file you uploaded was either not an image or a corrupted image."), 458 } 459 385 460 def clean(self, data): 386 461 """ 387 462 Checks that the file-upload field data contains a valid image (GIF, JPG, … … 402 477 trial_image = Image.open(StringIO(f.content)) 403 478 trial_image.verify() 404 479 except Exception: # Python Imaging Library doesn't recognize it as an image 405 raise ValidationError( ugettext(u"Upload a valid image. The file you uploaded was either not an image or a corrupted image."))480 raise ValidationError(self.error_messages['invalid_image']) 406 481 return f 407 482 408 483 url_re = re.compile( … … 414 489 r'(?:/?|/\S+)$', re.IGNORECASE) 415 490 416 491 class URLField(RegexField): 492 default_error_messages = { 493 'invalid': ugettext_lazy(u'Enter a valid URL.'), 494 'invalid_link': ugettext_lazy(u'This URL appears to be a broken link.'), 495 } 496 417 497 def __init__(self, max_length=None, min_length=None, verify_exists=False, 418 498 validator_user_agent=URL_VALIDATOR_USER_AGENT, *args, **kwargs): 419 super(URLField, self).__init__(url_re, max_length, min_length, ugettext(u'Enter a valid URL.'), *args, **kwargs) 499 super(URLField, self).__init__(url_re, max_length, min_length, *args, 500 **kwargs) 420 501 self.verify_exists = verify_exists 421 502 self.user_agent = validator_user_agent 422 503 … … 441 522 req = urllib2.Request(value, None, headers) 442 523 u = urllib2.urlopen(req) 443 524 except ValueError: 444 raise ValidationError( ugettext(u'Enter a valid URL.'))525 raise ValidationError(self.error_messages['invalid']) 445 526 except: # urllib2.URLError, httplib.InvalidURL, etc. 446 raise ValidationError( ugettext(u'This URL appears to be a broken link.'))527 raise ValidationError(self.error_messages['invalid_link']) 447 528 return value 448 529 449 530 class BooleanField(Field): … … 466 547 467 548 class ChoiceField(Field): 468 549 widget = Select 550 default_error_messages = { 551 'invalid_choice': ugettext_lazy(u'Select a valid choice. That choice is not one of the available choices.'), 552 } 469 553 470 def __init__(self, choices=(), required=True, widget=None, label=None, initial=None, help_text=None): 471 super(ChoiceField, self).__init__(required, widget, label, initial, help_text) 554 def __init__(self, choices=(), required=True, widget=None, label=None, 555 initial=None, help_text=None, *args, **kwargs): 556 super(ChoiceField, self).__init__(required, widget, label, initial, 557 help_text, *args, **kwargs) 472 558 self.choices = choices 473 559 474 560 def _get_choices(self): … … 494 580 return value 495 581 valid_values = set([smart_unicode(k) for k, v in self.choices]) 496 582 if value not in valid_values: 497 raise ValidationError( ugettext(u'Select a valid choice. That choice is not one of the available choices.'))583 raise ValidationError(self.error_messages['invalid_choice'] % {'value': value}) 498 584 return value 499 585 500 586 class MultipleChoiceField(ChoiceField): 501 587 hidden_widget = MultipleHiddenInput 502 588 widget = SelectMultiple 589 default_error_messages = { 590 'invalid_choice': ugettext_lazy(u'Select a valid choice. %(value)s is not one of the available choices.'), 591 'invalid_list': ugettext_lazy(u'Enter a list of values.'), 592 } 503 593 504 594 def clean(self, value): 505 595 """ 506 596 Validates that the input is a list or tuple. 507 597 """ 508 598 if self.required and not value: 509 raise ValidationError( ugettext(u'This field is required.'))599 raise ValidationError(self.error_messages['required']) 510 600 elif not self.required and not value: 511 601 return [] 512 602 if not isinstance(value, (list, tuple)): 513 raise ValidationError( ugettext(u'Enter a list of values.'))603 raise ValidationError(self.error_messages['invalid_list']) 514 604 new_value = [smart_unicode(val) for val in value] 515 605 # Validate that each value in the value list is in self.choices. 516 606 valid_values = set([smart_unicode(k) for k, v in self.choices]) 517 607 for val in new_value: 518 608 if val not in valid_values: 519 raise ValidationError( ugettext(u'Select a valid choice. %s is not one of the available choices.') % val)609 raise ValidationError(self.error_messages['invalid_choice'] % {'value': val}) 520 610 return new_value 521 611 522 612 class ComboField(Field): … … 559 649 560 650 You'll probably want to use this with MultiWidget. 561 651 """ 652 default_error_messages = { 653 'invalid': ugettext_lazy(u'Enter a list of values.'), 654 } 562 655 def __init__(self, fields=(), *args, **kwargs): 563 656 super(MultiValueField, self).__init__(*args, **kwargs) 564 657 # Set 'required' to False on the individual fields, because the … … 582 675 if not value or isinstance(value, (list, tuple)): 583 676 if not value or not [v for v in value if v not in EMPTY_VALUES]: 584 677 if self.required: 585 raise ValidationError( ugettext(u'This field is required.'))678 raise ValidationError(self.error_messages['required']) 586 679 else: 587 680 return self.compress([]) 588 681 else: 589 raise ValidationError( ugettext(u'Enter a list of values.'))682 raise ValidationError(self.error_messages['invalid']) 590 683 for i, field in enumerate(self.fields): 591 684 try: 592 685 field_value = value[i] 593 686 except IndexError: 594 687 field_value = None 595 688 if self.required and field_value in EMPTY_VALUES: 596 raise ValidationError( ugettext(u'This field is required.'))689 raise ValidationError(self.error_messages['required']) 597 690 try: 598 691 clean_data.append(field.clean(field_value)) 599 692 except ValidationError, e: … … 617 710 raise NotImplementedError('Subclasses must implement this method.') 618 711 619 712 class SplitDateTimeField(MultiValueField): 713 default_error_messages = { 714 'invalid_date': ugettext_lazy(u'Enter a valid date.'), 715 'invalid_time': ugettext_lazy(u'Enter a valid time.'), 716 } 620 717 def __init__(self, *args, **kwargs): 621 fields = (DateField(), TimeField()) 718 e = self.default_error_messages.copy() 719 if 'error_messages' in kwargs: 720 e.update(kwargs['error_messages']) 721 fields = (DateField(error_messages={'invalid': e['invalid_date']}), 722 TimeField(error_messages={'invalid': e['invalid_time']})) 622 723 super(SplitDateTimeField, self).__init__(fields, *args, **kwargs) 623 724 624 725 def compress(self, data_list): … … 626 727 # Raise a validation error if time or date is empty 627 728 # (possible if SplitDateTimeField has required=False). 628 729 if data_list[0] in EMPTY_VALUES: 629 raise ValidationError( ugettext(u'Enter a valid date.'))730 raise ValidationError(self.error_messages['invalid_date']) 630 731 if data_list[1] in EMPTY_VALUES: 631 raise ValidationError( ugettext(u'Enter a valid time.'))732 raise ValidationError(self.error_messages['invalid_time']) 632 733 return datetime.datetime.combine(*data_list) 633 734 return None -
tests/regressiontests/forms/util.py
42 42 # Can take a mixture in a list. 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 __str__(self): return "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 """ -
tests/regressiontests/forms/tests.py
940 940 >>> f.clean('1234567890a') 941 941 u'1234567890a' 942 942 943 Custom error messages 944 >>> e = {'required': 'REQUIRED'} 945 >>> e['min_length'] = 'LENGTH %(length)s, MIN LENGTH %(min)s' 946 >>> e['max_length'] = 'LENGTH %(length)s, MAX LENGTH %(max)s' 947 >>> f = CharField(min_length=5, max_length=10, error_messages=e) 948 >>> f.clean('') 949 Traceback (most recent call last): 950 ... 951 ValidationError: [u'REQUIRED'] 952 >>> f.clean('1234') 953 Traceback (most recent call last): 954 ... 955 ValidationError: [u'LENGTH 4, MIN LENGTH 5'] 956 >>> f.clean('12345678901') 957 Traceback (most recent call last): 958 ... 959 ValidationError: [u'LENGTH 11, MAX LENGTH 10'] 960 943 961 # IntegerField ################################################################ 944 962 945 963 >>> f = IntegerField() … … 1065 1083 ... 1066 1084 ValidationError: [u'Ensure this value is less than or equal to 20.'] 1067 1085 1086 Custom error messages 1087 >>> e = {'required': 'REQUIRED'} 1088 >>> e['invalid'] = 'INVALID' 1089 >>> e['min_value'] = 'MIN VALUE IS %s' 1090 >>> e['max_value'] = 'MAX VALUE IS %s' 1091 >>> f = IntegerField(min_value=5, max_value=10, error_messages=e) 1092 >>> f.clean('') 1093 Traceback (most recent call last): 1094 ... 1095 ValidationError: [u'REQUIRED'] 1096 >>> f.clean('abc') 1097 Traceback (most recent call last): 1098 ... 1099 ValidationError: [u'INVALID'] 1100 >>> f.clean('4') 1101 Traceback (most recent call last): 1102 ... 1103 ValidationError: [u'MIN VALUE IS 5'] 1104 >>> f.clean('11') 1105 Traceback (most recent call last): 1106 ... 1107 ValidationError: [u'MAX VALUE IS 10'] 1108 1068 1109 # FloatField ################################################################## 1069 1110 1070 1111 >>> f = FloatField() … … 1123 1164 >>> f.clean('0.5') 1124 1165 0.5 1125 1166 1167 Custom error messages 1168 >>> e = {'required': 'REQUIRED'} 1169 >>> e['invalid'] = 'INVALID' 1170 >>> e['min_value'] = 'MIN VALUE IS %s' 1171 >>> e['max_value'] = 'MAX VALUE IS %s' 1172 >>> f = FloatField(min_value=5, max_value=10, error_messages=e) 1173 >>> f.clean('') 1174 Traceback (most recent call last): 1175 ... 1176 ValidationError: [u'REQUIRED'] 1177 >>> f.clean('abc') 1178 Traceback (most recent call last): 1179 ... 1180 ValidationError: [u'INVALID'] 1181 >>> f.clean('4') 1182 Traceback (most recent call last): 1183 ... 1184 ValidationError: [u'MIN VALUE IS 5'] 1185 >>> f.clean('11') 1186 Traceback (most recent call last): 1187 ... 1188 ValidationError: [u'MAX VALUE IS 10'] 1189 1126 1190 # DecimalField ################################################################ 1127 1191 1128 1192 >>> f = DecimalField(max_digits=4, decimal_places=2) … … 1221 1285 >>> f.clean('00.50') 1222 1286 Decimal("0.50") 1223 1287 1288 Custom error messages 1289 >>> e = {'required': 'REQUIRED'} 1290 >>> e['invalid'] = 'INVALID' 1291 >>> e['min_value'] = 'MIN VALUE IS %s' 1292 >>> e['max_value'] = 'MAX VALUE IS %s' 1293 >>> e['max_digits'] = 'MAX DIGITS IS %s' 1294 >>> e['max_decimal_places'] = 'MAX DP IS %s' 1295 >>> e['max_whole_digits'] = 'MAX DIGITS BEFORE DP IS %s' 1296 >>> f = DecimalField(min_value=5, max_value=10, error_messages=e) 1297 >>> f2 = DecimalField(max_digits=4, decimal_places=2, error_messages=e) 1298 >>> f.clean('') 1299 Traceback (most recent call last): 1300 ... 1301 ValidationError: [u'REQUIRED'] 1302 >>> f.clean('abc') 1303 Traceback (most recent call last): 1304 ... 1305 ValidationError: [u'INVALID'] 1306 >>> f.clean('4') 1307 Traceback (most recent call last): 1308 ... 1309 ValidationError: [u'MIN VALUE IS 5'] 1310 >>> f.clean('11') 1311 Traceback (most recent call last): 1312 ... 1313 ValidationError: [u'MAX VALUE IS 10'] 1314 >>> f2.clean('123.45') 1315 Traceback (most recent call last): 1316 ... 1317 ValidationError: [u'MAX DIGITS IS 4'] 1318 >>> f2.clean('1.234') 1319 Traceback (most recent call last): 1320 ... 1321 ValidationError: [u'MAX DP IS 2'] 1322 >>> f2.clean('123.4') 1323 Traceback (most recent call last): 1324 ... 1325 ValidationError: [u'MAX DIGITS BEFORE DP IS 2'] 1326 1224 1327 # DateField ################################################################### 1225 1328 1226 1329 >>> import datetime … … 1298 1401 ... 1299 1402 ValidationError: [u'Enter a valid date.'] 1300 1403 1404 Custom error messages 1405 >>> e = {'required': 'REQUIRED'} 1406 >>> e['invalid'] = 'INVALID' 1407 >>> f = DateField(error_messages=e) 1408 >>> f.clean('') 1409 Traceback (most recent call last): 1410 ... 1411 ValidationError: [u'REQUIRED'] 1412 >>> f.clean('abc') 1413 Traceback (most recent call last): 1414 ... 1415 ValidationError: [u'INVALID'] 1416 1301 1417 # TimeField ################################################################### 1302 1418 1303 1419 >>> import datetime … … 1337 1453 ... 1338 1454 ValidationError: [u'Enter a valid time.'] 1339 1455 1456 Custom error messages 1457 >>> e = {'required': 'REQUIRED'} 1458 >>> e['invalid'] = 'INVALID' 1459 >>> f = TimeField(error_messages=e) 1460 >>> f.clean('') 1461 Traceback (most recent call last): 1462 ... 1463 ValidationError: [u'REQUIRED'] 1464 >>> f.clean('abc') 1465 Traceback (most recent call last): 1466 ... 1467 ValidationError: [u'INVALID'] 1468 1340 1469 # DateTimeField ############################################################### 1341 1470 1342 1471 >>> import datetime … … 1410 1539 >>> repr(f.clean('')) 1411 1540 'None' 1412 1541 1542 Custom error messages 1543 >>> e = {'required': 'REQUIRED'} 1544 >>> e['invalid'] = 'INVALID' 1545 >>> f = DateTimeField(error_messages=e) 1546 >>> f.clean('') 1547 Traceback (most recent call last): 1548 ... 1549 ValidationError: [u'REQUIRED'] 1550 >>> f.clean('abc') 1551 Traceback (most recent call last): 1552 ... 1553 ValidationError: [u'INVALID'] 1554 1413 1555 # RegexField ################################################################## 1414 1556 1415 1557 >>> f = RegexField('^\d[A-F]\d$') … … 1501 1643 ... 1502 1644 ValidationError: [u'Enter a valid value.'] 1503 1645 1646 Custom error messages 1647 >>> e = {'required': 'REQUIRED'} 1648 >>> e['invalid'] = 'INVALID' 1649 >>> e['min_length'] = 'LENGTH %(length)s, MIN LENGTH %(min)s' 1650 >>> e['max_length'] = 'LENGTH %(length)s, MAX LENGTH %(max)s' 1651 >>> f = RegexField(r'^\d+$', min_length=5, max_length=10, error_messages=e) 1652 >>> f.clean('') 1653 Traceback (most recent call last): 1654 ... 1655 ValidationError: [u'REQUIRED'] 1656 >>> f.clean('abcde') 1657 Traceback (most recent call last): 1658 ... 1659 ValidationError: [u'INVALID'] 1660 >>> f.clean('1234') 1661 Traceback (most recent call last): 1662 ... 1663 ValidationError: [u'LENGTH 4, MIN LENGTH 5'] 1664 >>> f.clean('12345678901') 1665 Traceback (most recent call last): 1666 ... 1667 ValidationError: [u'LENGTH 11, MAX LENGTH 10'] 1668 1504 1669 # EmailField ################################################################## 1505 1670 1506 1671 >>> f = EmailField() … … 1560 1725 ... 1561 1726 ValidationError: [u'Ensure this value has at most 15 characters (it has 20).'] 1562 1727 1728 Custom error messages 1729 >>> e = {'required': 'REQUIRED'} 1730 >>> e['invalid'] = 'INVALID' 1731 >>> e['min_length'] = 'LENGTH %(length)s, MIN LENGTH %(min)s' 1732 >>> e['max_length'] = 'LENGTH %(length)s, MAX LENGTH %(max)s' 1733 >>> f = EmailField(min_length=8, max_length=10, error_messages=e) 1734 >>> f.clean('') 1735 Traceback (most recent call last): 1736 ... 1737 ValidationError: [u'REQUIRED'] 1738 >>> f.clean('abcdefgh') 1739 Traceback (most recent call last): 1740 ... 1741 ValidationError: [u'INVALID'] 1742 >>> f.clean('a@b.com') 1743 Traceback (most recent call last): 1744 ... 1745 ValidationError: [u'LENGTH 7, MIN LENGTH 8'] 1746 >>> f.clean('aye@bee.com') 1747 Traceback (most recent call last): 1748 ... 1749 ValidationError: [u'LENGTH 11, MAX LENGTH 10'] 1750 1563 1751 # FileField ################################################################## 1564 1752 1565 1753 >>> f = FileField() … … 1596 1784 >>> type(f.clean({'filename': 'name', 'content':'Some File Content'})) 1597 1785 <class 'django.newforms.fields.UploadedFile'> 1598 1786 1787 Custom error messages 1788 >>> e = {'required': 'REQUIRED'} 1789 >>> e['invalid'] = 'INVALID' 1790 >>> e['missing'] = 'MISSING' 1791 >>> e['empty'] = 'EMPTY FILE' 1792 >>> f = FileField(error_messages=e) 1793 >>> f.clean('') 1794 Traceback (most recent call last): 1795 ... 1796 ValidationError: [u'REQUIRED'] 1797 >>> f.clean('abc') 1798 Traceback (most recent call last): 1799 ... 1800 ValidationError: [u'INVALID'] 1801 >>> f.clean({}) 1802 Traceback (most recent call last): 1803 ... 1804 ValidationError: [u'MISSING'] 1805 >>> f.clean({'filename': 'name', 'content':''}) 1806 Traceback (most recent call last): 1807 ... 1808 ValidationError: [u'EMPTY FILE'] 1809 1599 1810 # URLField ################################################################## 1600 1811 1601 1812 >>> f = URLField() … … 1715 1926 >>> f.clean('https://example.com') 1716 1927 u'https://example.com' 1717 1928 1929 Custom error messages 1930 >>> e = {'required': 'REQUIRED'} 1931 >>> e['invalid'] = 'INVALID' 1932 >>> e['invalid_link'] = 'INVALID LINK' 1933 >>> f = URLField(verify_exists=True, error_messages=e) 1934 >>> f.clean('') 1935 Traceback (most recent call last): 1936 ... 1937 ValidationError: [u'REQUIRED'] 1938 >>> f.clean('abc.c') 1939 Traceback (most recent call last): 1940 ... 1941 ValidationError: [u'INVALID'] 1942 >>> f.clean('http://www.jfoiwjfoi23jfoijoaijfoiwjofiwjefewl.com') 1943 Traceback (most recent call last): 1944 ... 1945 ValidationError: [u'INVALID LINK'] 1946 1718 1947 # BooleanField ################################################################ 1719 1948 1720 1949 >>> f = BooleanField() … … 1753 1982 >>> f.clean('Django rocks') 1754 1983 True 1755 1984 1985 Custom error messages 1986 >>> e = {'required': 'REQUIRED'} 1987 >>> f = BooleanField(error_messages=e) 1988 >>> f.clean('') 1989 Traceback (most recent call last): 1990 ... 1991 ValidationError: [u'REQUIRED'] 1992 1756 1993 # ChoiceField ################################################################# 1757 1994 1758 1995 >>> f = ChoiceField(choices=[('1', '1'), ('2', '2')]) … … 1795 2032 ... 1796 2033 ValidationError: [u'Select a valid choice. That choice is not one of the available choices.'] 1797 2034 2035 Custom error messages 2036 >>> e = {'required': 'REQUIRED'} 2037 >>> e['invalid_choice'] = '%(value)s IS INVALID CHOICE' 2038 >>> f = ChoiceField(choices=[('a', 'aye')], error_messages=e) 2039 >>> f.clean('') 2040 Traceback (most recent call last): 2041 ... 2042 ValidationError: [u'REQUIRED'] 2043 >>> f.clean('b') 2044 Traceback (most recent call last): 2045 ... 2046 ValidationError: [u'b IS INVALID CHOICE'] 2047 1798 2048 # NullBooleanField ############################################################ 1799 2049 1800 2050 >>> f = NullBooleanField() … … 1875 2125 ... 1876 2126 ValidationError: [u'Select a valid choice. 3 is not one of the available choices.'] 1877 2127 2128 Custom error messages 2129 >>> e = {'required': 'REQUIRED'} 2130 >>> e['invalid_choice'] = '%(value)s IS INVALID CHOICE' 2131 >>> e['invalid_list'] = 'NOT A LIST' 2132 >>> f = MultipleChoiceField(choices=[('a', 'aye')], error_messages=e) 2133 >>> f.clean('') 2134 Traceback (most recent call last): 2135 ... 2136 ValidationError: [u'REQUIRED'] 2137 >>> f.clean('b') 2138 Traceback (most recent call last): 2139 ... 2140 ValidationError: [u'NOT A LIST'] 2141 >>> f.clean(['b']) 2142 Traceback (most recent call last): 2143 ... 2144 ValidationError: [u'b IS INVALID CHOICE'] 2145 1878 2146 # ComboField ################################################################## 1879 2147 1880 2148 ComboField takes a list of fields that should be used to validate a value, … … 1983 2251 ... 1984 2252 ValidationError: [u'Enter a valid date.'] 1985 2253 2254 Custom error messages 2255 >>> e = {'required': 'REQUIRED'} 2256 >>> e['invalid_date'] = 'INVALID DATE' 2257 >>> e['invalid_time'] = 'INVALID TIME' 2258 >>> f = SplitDateTimeField(error_messages=e) 2259 >>> f.clean('') 2260 Traceback (most recent call last): 2261 ... 2262 ValidationError: [u'REQUIRED'] 2263 >>> f.clean(['a', 'b']) 2264 Traceback (most recent call last): 2265 ... 2266 ValidationError: [u'INVALID DATE', u'INVALID TIME'] 2267 1986 2268 ######### 1987 2269 # Forms # 1988 2270 ######### -
docs/newforms.txt
1020 1020 <p>Sender: <input type="text" name="sender" /> A valid e-mail address, please.</p> 1021 1021 <p>Cc myself: <input type="checkbox" name="cc_myself" /></p> 1022 1022 1023 ``error_messages`` 1024 ~~~~~~~~~~~~~~~~~~ 1025 1026 The ``error_messages`` argument lets you override the default messages which the 1027 field will raise. Pass in a dictionary with keys matching the error messages you 1028 want to override. For example:: 1029 1030 >>> generic = forms.CharField() 1031 >>> generic.clean('') 1032 Traceback (most recent call last): 1033 ... 1034 ValidationError: [u'This field is required.'] 1035 1036 >>> name = forms.CharField(error_messages={'required': 'Please enter your name'}) 1037 >>> name.clean('') 1038 Traceback (most recent call last): 1039 ... 1040 ValidationError: [u'Please enter your name'] 1041 1042 In the `built-in Field classes`_ section below, each Field defines the error 1043 message keys it uses. 1044 1023 1045 Dynamic initial values 1024 1046 ---------------------- 1025 1047 … … 1084 1106 * Empty value: ``None`` 1085 1107 * Normalizes to: A Python ``True`` or ``False`` value. 1086 1108 * Validates nothing (i.e., it never raises a ``ValidationError``). 1109 * Error message keys: ``required`` 1087 1110 1088 1111 ``CharField`` 1089 1112 ~~~~~~~~~~~~~ … … 1092 1115 * Empty value: ``''`` (an empty string) 1093 1116 * Normalizes to: A Unicode object. 1094 1117 * Validates nothing, unless ``max_length`` or ``min_length`` is provided. 1118 * Error message keys: ``required``, ``max_length``, ``min_length`` 1095 1119 1096 1120 Has two optional arguments for validation, ``max_length`` and ``min_length``. 1097 1121 If provided, these arguments ensure that the string is at most or at least the … … 1104 1128 * Empty value: ``''`` (an empty string) 1105 1129 * Normalizes to: A Unicode object. 1106 1130 * Validates that the given value exists in the list of choices. 1131 * Error message keys: ``required``, ``invalid_choice`` 1107 1132 1108 1133 Takes one extra argument, ``choices``, which is an iterable (e.g., a list or 1109 1134 tuple) of 2-tuples to use as choices for this field. … … 1116 1141 * Normalizes to: A Python ``datetime.date`` object. 1117 1142 * Validates that the given value is either a ``datetime.date``, 1118 1143 ``datetime.datetime`` or string formatted in a particular date format. 1144 * Error message keys: ``required``, ``invalid`` 1119 1145 1120 1146 Takes one optional argument, ``input_formats``, which is a list of formats used 1121 1147 to attempt to convert a string to a valid ``datetime.date`` object. … … 1136 1162 * Normalizes to: A Python ``datetime.datetime`` object. 1137 1163 * Validates that the given value is either a ``datetime.datetime``, 1138 1164 ``datetime.date`` or string formatted in a particular datetime format. 1165 * Error message keys: ``required``, ``invalid`` 1139 1166 1140 1167 Takes one optional argument, ``input_formats``, which is a list of formats used 1141 1168 to attempt to convert a string to a valid ``datetime.datetime`` object. … … 1162 1189 * Normalizes to: A Python ``decimal``. 1163 1190 * Validates that the given value is a decimal. Leading and trailing 1164 1191 whitespace is ignored. 1192 * Error message keys: ``required``, ``invalid``, ``max_value``, 1193 ``min_value``, ``max_digits``, ``max_decimal_places``, 1194 ``max_whole_digits`` 1165 1195 1166 1196 Takes four optional arguments: ``max_value``, ``min_value``, ``max_digits``, 1167 1197 and ``decimal_places``. The first two define the limits for the fields value. … … 1178 1208 * Normalizes to: A Unicode object. 1179 1209 * Validates that the given value is a valid e-mail address, using a 1180 1210 moderately complex regular expression. 1211 * Error message keys: ``required``, ``invalid`` 1181 1212 1182 1213 Has two optional arguments for validation, ``max_length`` and ``min_length``. 1183 1214 If provided, these arguments ensure that the string is at most or at least the … … 1193 1224 * Normalizes to: An ``UploadedFile`` object that wraps the file content 1194 1225 and file name into a single object. 1195 1226 * Validates that non-empty file data has been bound to the form. 1227 * Error message keys: ``required``, ``invalid``, ``missing``, ``empty`` 1196 1228 1197 1229 An ``UploadedFile`` object has two attributes: 1198 1230 … … 1223 1255 and file name into a single object. 1224 1256 * Validates that file data has been bound to the form, and that the 1225 1257 file is of an image format understood by PIL. 1258 * Error message keys: ``required``, ``invalid``, ``missing``, ``empty``, 1259 ``invalid_image`` 1226 1260 1227 1261 Using an ImageField requires that the `Python Imaging Library`_ is installed. 1228 1262 … … 1239 1273 * Normalizes to: A Python integer or long integer. 1240 1274 * Validates that the given value is an integer. Leading and trailing 1241 1275 whitespace is allowed, as in Python's ``int()`` function. 1276 * Error message keys: ``required``, ``invalid``, ``max_value``, 1277 ``min_value`` 1242 1278 1243 1279 Takes two optional arguments for validation, ``max_value`` and ``min_value``. 1244 1280 These control the range of values permitted in the field. … … 1251 1287 * Normalizes to: A list of Unicode objects. 1252 1288 * Validates that every value in the given list of values exists in the list 1253 1289 of choices. 1290 * Error message keys: ``required``, ``invalid_choice``, ``invalid_list`` 1254 1291 1255 1292 Takes one extra argument, ``choices``, which is an iterable (e.g., a list or 1256 1293 tuple) of 2-tuples to use as choices for this field. … … 1271 1308 * Normalizes to: A Unicode object. 1272 1309 * Validates that the given value matches against a certain regular 1273 1310 expression. 1311 * Error message keys: ``required``, ``invalid`` 1274 1312 1275 1313 Takes one required argument, ``regex``, which is a regular expression specified 1276 1314 either as a string or a compiled regular expression object. … … 1282 1320 ====================== ===================================================== 1283 1321 ``max_length`` Ensures the string has at most this many characters. 1284 1322 ``min_length`` Ensures the string has at least this many characters. 1285 ``error_message`` Error message to return for failed validation. If no1286 message is provided, a generic error message will be1287 used.1288 1323 ====================== ===================================================== 1289 1324 1325 The optional argument ``error_message`` is also accepted for backwards 1326 compatibility. The preferred way to provide an error message is to use the 1327 ``error_messages`` argument, passing a dictionary with ``'invalid'`` as a key 1328 and the error message as the value. 1329 1290 1330 ``TimeField`` 1291 1331 ~~~~~~~~~~~~~ 1292 1332 … … 1295 1335 * Normalizes to: A Python ``datetime.time`` object. 1296 1336 * Validates that the given value is either a ``datetime.time`` or string 1297 1337 formatted in a particular time format. 1338 * Error message keys: ``required``, ``invalid`` 1298 1339 1299 1340 Takes one optional argument, ``input_formats``, which is a list of formats used 1300 1341 to attempt to convert a string to a valid ``datetime.time`` object. … … 1311 1352 * Empty value: ``''`` (an empty string) 1312 1353 * Normalizes to: A Unicode object. 1313 1354 * Validates that the given value is a valid URL. 1355 * Error message keys: ``required``, ``invalid``, ``invalid_link`` 1314 1356 1315 1357 Takes the following optional arguments: 1316 1358