Ticket #3457: newforms_error_messages.3.patch
File newforms_error_messages.3.patch, 40.6 KB (added by , 17 years ago) |
---|
-
django/newforms/fields.py
6 6 import re 7 7 import time 8 8 9 from django.utils.translation import ugettext 9 from django.utils.translation import ugettext_lazy 10 10 from django.utils.encoding import StrAndUnicode, smart_unicode 11 11 12 12 from util import ErrorList, ValidationError … … 44 44 class Field(object): 45 45 widget = TextInput # Default widget to use when rendering this type of Field. 46 46 hidden_widget = HiddenInput # Default widget to use when rendering this as "hidden". 47 default_error_messages = { 48 'required': ugettext_lazy(u'This field is required.'), 49 'invalid': ugettext_lazy(u'Enter a valid value.'), 50 } 47 51 48 52 # Tracks each time a Field instance is created. Used to retain order. 49 53 creation_counter = 0 50 54 51 def __init__(self, required=True, widget=None, label=None, initial=None, help_text=None): 55 def __init__(self, required=True, widget=None, label=None, initial=None, 56 help_text=None, error_messages=None): 52 57 # required -- Boolean that specifies whether the field is required. 53 58 # True by default. 54 59 # widget -- A Widget class, or instance of a Widget class, that should … … 81 86 self.creation_counter = Field.creation_counter 82 87 Field.creation_counter += 1 83 88 89 self.error_messages = self._build_error_messages(error_messages) 90 91 def _build_error_messages(self, extra_error_messages): 92 error_messages = {} 93 def get_default_error_messages(klass): 94 for base_class in klass.__bases__: 95 get_default_error_messages(base_class) 96 if hasattr(klass, 'default_error_messages'): 97 error_messages.update(klass.default_error_messages) 98 get_default_error_messages(self.__class__) 99 if extra_error_messages: 100 error_messages.update(extra_error_messages) 101 return error_messages 102 84 103 def clean(self, value): 85 104 """ 86 105 Validates the given value and returns its "cleaned" value as an … … 89 108 Raises ValidationError for any errors. 90 109 """ 91 110 if self.required and value in EMPTY_VALUES: 92 raise ValidationError( ugettext(u'This field is required.'))111 raise ValidationError(self.error_messages['required']) 93 112 return value 94 113 95 114 def widget_attrs(self, widget): … … 101 120 return {} 102 121 103 122 class CharField(Field): 123 default_error_messages = { 124 'max_length': ugettext_lazy(u'Ensure this value has at most %(max)d characters (it has %(length)d).'), 125 'min_length': ugettext_lazy(u'Ensure this value has at least %(min)d characters (it has %(length)d).'), 126 } 127 104 128 def __init__(self, max_length=None, min_length=None, *args, **kwargs): 105 129 self.max_length, self.min_length = max_length, min_length 106 130 super(CharField, self).__init__(*args, **kwargs) … … 113 137 value = smart_unicode(value) 114 138 value_length = len(value) 115 139 if self.max_length is not None and value_length > self.max_length: 116 raise ValidationError( ugettext(u'Ensure this value has at most %(max)d characters (it has %(length)d).')% {'max': self.max_length, 'length': value_length})140 raise ValidationError(self.error_messages['max_length'] % {'max': self.max_length, 'length': value_length}) 117 141 if self.min_length is not None and value_length < self.min_length: 118 raise ValidationError( ugettext(u'Ensure this value has at least %(min)d characters (it has %(length)d).')% {'min': self.min_length, 'length': value_length})142 raise ValidationError(self.error_messages['min_length'] % {'min': self.min_length, 'length': value_length}) 119 143 return value 120 144 121 145 def widget_attrs(self, widget): … … 124 148 return {'maxlength': str(self.max_length)} 125 149 126 150 class IntegerField(Field): 151 default_error_messages = { 152 'invalid': ugettext_lazy(u'Enter a whole number.'), 153 'max_value': ugettext_lazy(u'Ensure this value is less than or equal to %s.'), 154 'min_value': ugettext_lazy(u'Ensure this value is greater than or equal to %s.'), 155 } 156 127 157 def __init__(self, max_value=None, min_value=None, *args, **kwargs): 128 158 self.max_value, self.min_value = max_value, min_value 129 159 super(IntegerField, self).__init__(*args, **kwargs) … … 139 169 try: 140 170 value = int(value) 141 171 except (ValueError, TypeError): 142 raise ValidationError( ugettext(u'Enter a whole number.'))172 raise ValidationError(self.error_messages['invalid']) 143 173 if self.max_value is not None and value > self.max_value: 144 raise ValidationError( ugettext(u'Ensure this value is less than or equal to %s.')% self.max_value)174 raise ValidationError(self.error_messages['max_value'] % self.max_value) 145 175 if self.min_value is not None and value < self.min_value: 146 raise ValidationError( ugettext(u'Ensure this value is greater than or equal to %s.')% self.min_value)176 raise ValidationError(self.error_messages['min_value'] % self.min_value) 147 177 return value 148 178 149 179 class FloatField(Field): 180 default_error_messages = { 181 'invalid': ugettext_lazy(u'Enter a number.'), 182 'max_value': ugettext_lazy(u'Ensure this value is less than or equal to %s.'), 183 'min_value': ugettext_lazy(u'Ensure this value is greater than or equal to %s.'), 184 } 185 150 186 def __init__(self, max_value=None, min_value=None, *args, **kwargs): 151 187 self.max_value, self.min_value = max_value, min_value 152 188 Field.__init__(self, *args, **kwargs) … … 162 198 try: 163 199 value = float(value) 164 200 except (ValueError, TypeError): 165 raise ValidationError( ugettext('Enter a number.'))201 raise ValidationError(self.error_messages['invalid']) 166 202 if self.max_value is not None and value > self.max_value: 167 raise ValidationError( ugettext('Ensure this value is less than or equal to %s.')% self.max_value)203 raise ValidationError(self.error_messages['max_value'] % self.max_value) 168 204 if self.min_value is not None and value < self.min_value: 169 raise ValidationError( ugettext('Ensure this value is greater than or equal to %s.')% self.min_value)205 raise ValidationError(self.error_messages['min_value'] % self.min_value) 170 206 return value 171 207 172 208 class DecimalField(Field): 209 default_error_messages = { 210 'invalid': ugettext_lazy(u'Enter a number.'), 211 'max_value': ugettext_lazy(u'Ensure this value is less than or equal to %s.'), 212 'min_value': ugettext_lazy(u'Ensure this value is greater than or equal to %s.'), 213 'max_digits': ugettext_lazy('Ensure that there are no more than %s digits in total.'), 214 'max_decimal_places': ugettext_lazy('Ensure that there are no more than %s decimal places.'), 215 'max_whole_digits': ugettext_lazy('Ensure that there are no more than %s digits before the decimal point.') 216 } 217 173 218 def __init__(self, max_value=None, min_value=None, max_digits=None, decimal_places=None, *args, **kwargs): 174 219 self.max_value, self.min_value = max_value, min_value 175 220 self.max_digits, self.decimal_places = max_digits, decimal_places … … 189 234 try: 190 235 value = Decimal(value) 191 236 except DecimalException: 192 raise ValidationError( ugettext('Enter a number.'))237 raise ValidationError(self.error_messages['invalid']) 193 238 pieces = str(value).lstrip("-").split('.') 194 239 decimals = (len(pieces) == 2) and len(pieces[1]) or 0 195 240 digits = len(pieces[0]) 196 241 if self.max_value is not None and value > self.max_value: 197 raise ValidationError( ugettext('Ensure this value is less than or equal to %s.')% self.max_value)242 raise ValidationError(self.error_messages['max_value'] % self.max_value) 198 243 if self.min_value is not None and value < self.min_value: 199 raise ValidationError( ugettext('Ensure this value is greater than or equal to %s.')% self.min_value)244 raise ValidationError(self.error_messages['min_value'] % self.min_value) 200 245 if self.max_digits is not None and (digits + decimals) > self.max_digits: 201 raise ValidationError( ugettext('Ensure that there are no more than %s digits in total.')% self.max_digits)246 raise ValidationError(self.error_messages['max_digits'] % self.max_digits) 202 247 if self.decimal_places is not None and decimals > self.decimal_places: 203 raise ValidationError( ugettext('Ensure that there are no more than %s decimal places.')% self.decimal_places)248 raise ValidationError(self.error_messages['max_decimal_places'] % self.decimal_places) 204 249 if self.max_digits is not None and self.decimal_places is not None and digits > (self.max_digits - self.decimal_places): 205 raise ValidationError( ugettext('Ensure that there are no more than %s digits before the decimal point.')% (self.max_digits - self.decimal_places))250 raise ValidationError(self.error_messages['max_whole_digits'] % (self.max_digits - self.decimal_places)) 206 251 return value 207 252 208 253 DEFAULT_DATE_INPUT_FORMATS = ( … … 214 259 ) 215 260 216 261 class DateField(Field): 262 default_error_messages = { 263 'invalid': ugettext_lazy(u'Enter a valid date.'), 264 } 265 217 266 def __init__(self, input_formats=None, *args, **kwargs): 218 267 super(DateField, self).__init__(*args, **kwargs) 219 268 self.input_formats = input_formats or DEFAULT_DATE_INPUT_FORMATS … … 235 284 return datetime.date(*time.strptime(value, format)[:3]) 236 285 except ValueError: 237 286 continue 238 raise ValidationError( ugettext(u'Enter a valid date.'))287 raise ValidationError(self.error_messages['invalid']) 239 288 240 289 DEFAULT_TIME_INPUT_FORMATS = ( 241 290 '%H:%M:%S', # '14:30:59' … … 243 292 ) 244 293 245 294 class TimeField(Field): 295 default_error_messages = { 296 'invalid': ugettext_lazy(u'Enter a valid time.') 297 } 298 246 299 def __init__(self, input_formats=None, *args, **kwargs): 247 300 super(TimeField, self).__init__(*args, **kwargs) 248 301 self.input_formats = input_formats or DEFAULT_TIME_INPUT_FORMATS … … 262 315 return datetime.time(*time.strptime(value, format)[3:6]) 263 316 except ValueError: 264 317 continue 265 raise ValidationError( ugettext(u'Enter a valid time.'))318 raise ValidationError(self.error_messages['invalid']) 266 319 267 320 DEFAULT_DATETIME_INPUT_FORMATS = ( 268 321 '%Y-%m-%d %H:%M:%S', # '2006-10-25 14:30:59' … … 277 330 ) 278 331 279 332 class DateTimeField(Field): 333 default_error_messages = { 334 'invalid': ugettext_lazy(u'Enter a valid date/time.'), 335 } 336 280 337 def __init__(self, input_formats=None, *args, **kwargs): 281 338 super(DateTimeField, self).__init__(*args, **kwargs) 282 339 self.input_formats = input_formats or DEFAULT_DATETIME_INPUT_FORMATS … … 298 355 return datetime.datetime(*time.strptime(value, format)[:6]) 299 356 except ValueError: 300 357 continue 301 raise ValidationError( ugettext(u'Enter a valid date/time.'))358 raise ValidationError(self.error_messages['invalid']) 302 359 303 360 class RegexField(CharField): 304 361 def __init__(self, regex, max_length=None, min_length=None, error_message=None, *args, **kwargs): … … 307 364 error_message is an optional error message to use, if 308 365 'Enter a valid value' is too generic for you. 309 366 """ 367 # error_message is just kept for backwards compatibility: 368 if error_message: 369 error_messages = kwargs.get('error_messages') or {} 370 error_messages['invalid'] = error_message 371 kwargs['error_messages'] = error_messages 310 372 super(RegexField, self).__init__(max_length, min_length, *args, **kwargs) 311 373 if isinstance(regex, basestring): 312 374 regex = re.compile(regex) 313 375 self.regex = regex 314 self.error_message = error_message or ugettext(u'Enter a valid value.')315 376 316 377 def clean(self, value): 317 378 """ … … 322 383 if value == u'': 323 384 return value 324 385 if not self.regex.search(value): 325 raise ValidationError(self.error_message )386 raise ValidationError(self.error_messages['invalid']) 326 387 return value 327 388 328 389 email_re = re.compile( … … 331 392 r')@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$', re.IGNORECASE) # domain 332 393 333 394 class EmailField(RegexField): 395 default_error_messages = { 396 'invalid': ugettext_lazy(u'Enter a valid e-mail address.'), 397 } 398 334 399 def __init__(self, max_length=None, min_length=None, *args, **kwargs): 335 RegexField.__init__(self, email_re, max_length, min_length, 336 ugettext(u'Enter a valid e-mail address.'), *args,**kwargs)400 RegexField.__init__(self, email_re, max_length, min_length, *args, 401 **kwargs) 337 402 338 403 url_re = re.compile( 339 404 r'^https?://' # http:// or https:// … … 363 428 364 429 class FileField(Field): 365 430 widget = FileInput 431 default_error_messages = { 432 'invalid': ugettext_lazy(u"No file was submitted. Check the encoding type on the form."), 433 'missing': ugettext_lazy(u"No file was submitted."), 434 'empty': ugettext_lazy(u"The submitted file is empty."), 435 } 436 366 437 def __init__(self, *args, **kwargs): 367 438 super(FileField, self).__init__(*args, **kwargs) 368 439 … … 373 444 try: 374 445 f = UploadedFile(data['filename'], data['content']) 375 446 except TypeError: 376 raise ValidationError( ugettext(u"No file was submitted. Check the encoding type on the form."))447 raise ValidationError(self.error_messages['invalid']) 377 448 except KeyError: 378 raise ValidationError( ugettext(u"No file was submitted."))449 raise ValidationError(self.error_messages['missing']) 379 450 if not f.content: 380 raise ValidationError( ugettext(u"The submitted file is empty."))451 raise ValidationError(self.error_messages['empty']) 381 452 return f 382 453 383 454 class ImageField(FileField): 455 default_error_messages = { 456 'invalid_image': ugettext_lazy(u"Upload a valid image. The file you uploaded was either not an image or a corrupted image."), 457 } 458 384 459 def clean(self, data): 385 460 """ 386 461 Checks that the file-upload field data contains a valid image (GIF, JPG, … … 394 469 try: 395 470 Image.open(StringIO(f.content)) 396 471 except IOError: # Python Imaging Library doesn't recognize it as an image 397 raise ValidationError( ugettext(u"Upload a valid image. The file you uploaded was either not an image or a corrupted image."))472 raise ValidationError(self.error_messages['invalid_image']) 398 473 return f 399 474 400 475 class URLField(RegexField): 476 default_error_messages = { 477 'invalid': ugettext_lazy(u'Enter a valid URL.'), 478 'invalid_link': ugettext_lazy(u'This URL appears to be a broken link.'), 479 } 480 401 481 def __init__(self, max_length=None, min_length=None, verify_exists=False, 402 482 validator_user_agent=URL_VALIDATOR_USER_AGENT, *args, **kwargs): 403 super(URLField, self).__init__(url_re, max_length, min_length, ugettext(u'Enter a valid URL.'), *args, **kwargs) 483 super(URLField, self).__init__(url_re, max_length, min_length, *args, 484 **kwargs) 404 485 self.verify_exists = verify_exists 405 486 self.user_agent = validator_user_agent 406 487 … … 422 503 req = urllib2.Request(value, None, headers) 423 504 u = urllib2.urlopen(req) 424 505 except ValueError: 425 raise ValidationError( ugettext(u'Enter a valid URL.'))506 raise ValidationError(self.error_messages['invalid']) 426 507 except: # urllib2.URLError, httplib.InvalidURL, etc. 427 raise ValidationError( ugettext(u'This URL appears to be a broken link.'))508 raise ValidationError(self.error_messages['invalid_link']) 428 509 return value 429 510 430 511 class BooleanField(Field): … … 447 528 448 529 class ChoiceField(Field): 449 530 widget = Select 531 default_error_messages = { 532 'invalid_choice': ugettext_lazy(u'Select a valid choice. That choice is not one of the available choices.'), 533 } 450 534 451 def __init__(self, choices=(), required=True, widget=None, label=None, initial=None, help_text=None): 452 super(ChoiceField, self).__init__(required, widget, label, initial, help_text) 535 def __init__(self, choices=(), required=True, widget=None, label=None, 536 initial=None, help_text=None, *args, **kwargs): 537 super(ChoiceField, self).__init__(required, widget, label, initial, 538 help_text, *args, **kwargs) 453 539 self.choices = choices 454 540 455 541 def _get_choices(self): … … 475 561 return value 476 562 valid_values = set([smart_unicode(k) for k, v in self.choices]) 477 563 if value not in valid_values: 478 raise ValidationError( ugettext(u'Select a valid choice. That choice is not one of the available choices.'))564 raise ValidationError(self.error_messages['invalid_choice'] % {'value': value}) 479 565 return value 480 566 481 567 class MultipleChoiceField(ChoiceField): 482 568 hidden_widget = MultipleHiddenInput 483 569 widget = SelectMultiple 570 default_error_messages = { 571 'invalid_choice': ugettext_lazy(u'Select a valid choice. %(value)s is not one of the available choices.'), 572 'invalid_list': ugettext_lazy(u'Enter a list of values.'), 573 } 484 574 485 575 def clean(self, value): 486 576 """ 487 577 Validates that the input is a list or tuple. 488 578 """ 489 579 if self.required and not value: 490 raise ValidationError( ugettext(u'This field is required.'))580 raise ValidationError(self.error_messages['required']) 491 581 elif not self.required and not value: 492 582 return [] 493 583 if not isinstance(value, (list, tuple)): 494 raise ValidationError( ugettext(u'Enter a list of values.'))584 raise ValidationError(self.error_messages['invalid_list']) 495 585 new_value = [smart_unicode(val) for val in value] 496 586 # Validate that each value in the value list is in self.choices. 497 587 valid_values = set([smart_unicode(k) for k, v in self.choices]) 498 588 for val in new_value: 499 589 if val not in valid_values: 500 raise ValidationError( ugettext(u'Select a valid choice. %s is not one of the available choices.') % val)590 raise ValidationError(self.error_messages['invalid_choice'] % {'value': val}) 501 591 return new_value 502 592 503 593 class ComboField(Field): … … 540 630 541 631 You'll probably want to use this with MultiWidget. 542 632 """ 633 default_error_messages = { 634 'invalid': ugettext_lazy(u'Enter a list of values.'), 635 } 543 636 def __init__(self, fields=(), *args, **kwargs): 544 637 super(MultiValueField, self).__init__(*args, **kwargs) 545 638 # Set 'required' to False on the individual fields, because the … … 563 656 if not value or isinstance(value, (list, tuple)): 564 657 if not value or not [v for v in value if v not in EMPTY_VALUES]: 565 658 if self.required: 566 raise ValidationError( ugettext(u'This field is required.'))659 raise ValidationError(self.error_messages['required']) 567 660 else: 568 661 return self.compress([]) 569 662 else: 570 raise ValidationError( ugettext(u'Enter a list of values.'))663 raise ValidationError(self.error_messages['invalid']) 571 664 for i, field in enumerate(self.fields): 572 665 try: 573 666 field_value = value[i] 574 667 except IndexError: 575 668 field_value = None 576 669 if self.required and field_value in EMPTY_VALUES: 577 raise ValidationError( ugettext(u'This field is required.'))670 raise ValidationError(self.error_messages['required']) 578 671 try: 579 672 clean_data.append(field.clean(field_value)) 580 673 except ValidationError, e: … … 598 691 raise NotImplementedError('Subclasses must implement this method.') 599 692 600 693 class SplitDateTimeField(MultiValueField): 694 default_error_messages = { 695 'invalid_date': ugettext_lazy(u'Enter a valid date.'), 696 'invalid_time': ugettext_lazy(u'Enter a valid time.'), 697 } 601 698 def __init__(self, *args, **kwargs): 602 fields = (DateField(), TimeField()) 699 e = self.default_error_messages.copy() 700 if 'error_messages' in kwargs: 701 e.update(kwargs['error_messages']) 702 fields = (DateField(error_messages={'invalid': e['invalid_date']}), 703 TimeField(error_messages={'invalid': e['invalid_time']})) 603 704 super(SplitDateTimeField, self).__init__(fields, *args, **kwargs) 604 705 605 706 def compress(self, data_list): … … 607 708 # Raise a validation error if time or date is empty 608 709 # (possible if SplitDateTimeField has required=False). 609 710 if data_list[0] in EMPTY_VALUES: 610 raise ValidationError( ugettext(u'Enter a valid date.'))711 raise ValidationError(self.error_messages['invalid_date']) 611 712 if data_list[1] in EMPTY_VALUES: 612 raise ValidationError( ugettext(u'Enter a valid time.'))713 raise ValidationError(self.error_messages['invalid_time']) 613 714 return datetime.datetime.combine(*data_list) 614 715 return None -
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 4 4 def flatatt(attrs): 5 5 """ … … 41 41 if not self: return u'' 42 42 return u'\n'.join([u'* %s' % smart_unicode(e) for e in self]) 43 43 44 def __repr__(self): 45 return repr([force_unicode(e) for e in self]) 46 44 47 class ValidationError(Exception): 45 48 def __init__(self, message): 46 49 "ValidationError can be passed a string or a list." 47 50 if isinstance(message, list): 48 51 self.messages = ErrorList([smart_unicode(msg) for msg in message]) 49 52 else: 50 assert isinstance(message, basestring), ("%s should be a basestring" % repr(message))51 53 message = smart_unicode(message) 52 54 self.messages = ErrorList([message]) 53 55 -
docs/newforms.txt
997 997 <p>Sender: <input type="text" name="sender" /> A valid e-mail address, please.</p> 998 998 <p>Cc myself: <input type="checkbox" name="cc_myself" /></p> 999 999 1000 ``error_messages`` 1001 ~~~~~~~~~~~~~~~~~~ 1002 1003 The ``error_messages`` argument lets you override the default messages which the 1004 field will raise. Pass in a dictionary with keys matching the error messages you 1005 want to override. For example:: 1006 1007 >>> generic = forms.CharField() 1008 >>> generic.clean('') 1009 Traceback (most recent call last): 1010 ... 1011 ValidationError: [u'This field is required.'] 1012 1013 >>> name = forms.CharField(error_messages={'required': 'Please enter your name'}) 1014 >>> name.clean('') 1015 Traceback (most recent call last): 1016 ... 1017 ValidationError: [u'Please enter your name'] 1018 1019 In the `built-in Field classes`_ section below, each Field defines the error 1020 message keys it uses. 1021 1000 1022 Dynamic initial values 1001 1023 ---------------------- 1002 1024 … … 1061 1083 * Empty value: ``None`` 1062 1084 * Normalizes to: A Python ``True`` or ``False`` value. 1063 1085 * Validates nothing (i.e., it never raises a ``ValidationError``). 1086 * Error message keys: ``required`` 1064 1087 1065 1088 ``CharField`` 1066 1089 ~~~~~~~~~~~~~ … … 1069 1092 * Empty value: ``''`` (an empty string) 1070 1093 * Normalizes to: A Unicode object. 1071 1094 * Validates nothing, unless ``max_length`` or ``min_length`` is provided. 1095 * Error message keys: ``required``, ``max_length``, ``min_length`` 1072 1096 1073 1097 Has two optional arguments for validation, ``max_length`` and ``min_length``. 1074 1098 If provided, these arguments ensure that the string is at most or at least the … … 1081 1105 * Empty value: ``''`` (an empty string) 1082 1106 * Normalizes to: A Unicode object. 1083 1107 * Validates that the given value exists in the list of choices. 1108 * Error message keys: ``required``, ``invalid_choice`` 1084 1109 1085 1110 Takes one extra argument, ``choices``, which is an iterable (e.g., a list or 1086 1111 tuple) of 2-tuples to use as choices for this field. … … 1093 1118 * Normalizes to: A Python ``datetime.date`` object. 1094 1119 * Validates that the given value is either a ``datetime.date``, 1095 1120 ``datetime.datetime`` or string formatted in a particular date format. 1121 * Error message keys: ``required``, ``invalid`` 1096 1122 1097 1123 Takes one optional argument, ``input_formats``, which is a list of formats used 1098 1124 to attempt to convert a string to a valid ``datetime.date`` object. … … 1113 1139 * Normalizes to: A Python ``datetime.datetime`` object. 1114 1140 * Validates that the given value is either a ``datetime.datetime``, 1115 1141 ``datetime.date`` or string formatted in a particular datetime format. 1142 * Error message keys: ``required``, ``invalid`` 1116 1143 1117 1144 Takes one optional argument, ``input_formats``, which is a list of formats used 1118 1145 to attempt to convert a string to a valid ``datetime.datetime`` object. … … 1139 1166 * Normalizes to: A Python ``decimal``. 1140 1167 * Validates that the given value is a decimal. Leading and trailing 1141 1168 whitespace is ignored. 1169 * Error message keys: ``required``, ``invalid``, ``max_value``, 1170 ``min_value``, ``max_digits``, ``max_decimal_places``, 1171 ``max_whole_digits`` 1142 1172 1143 1173 Takes four optional arguments: ``max_value``, ``min_value``, ``max_digits``, 1144 1174 and ``decimal_places``. The first two define the limits for the fields value. … … 1155 1185 * Normalizes to: A Unicode object. 1156 1186 * Validates that the given value is a valid e-mail address, using a 1157 1187 moderately complex regular expression. 1188 * Error message keys: ``required``, ``invalid`` 1158 1189 1159 1190 Has two optional arguments for validation, ``max_length`` and ``min_length``. 1160 1191 If provided, these arguments ensure that the string is at most or at least the … … 1170 1201 * Normalizes to: An ``UploadedFile`` object that wraps the file content 1171 1202 and file name into a single object. 1172 1203 * Validates that non-empty file data has been bound to the form. 1204 * Error message keys: ``required``, ``invalid``, ``missing``, ``empty`` 1173 1205 1174 1206 An ``UploadedFile`` object has two attributes: 1175 1207 … … 1200 1232 and file name into a single object. 1201 1233 * Validates that file data has been bound to the form, and that the 1202 1234 file is of an image format understood by PIL. 1235 * Error message keys: ``required``, ``invalid``, ``missing``, ``empty``, 1236 ``invalid_image`` 1203 1237 1204 1238 Using an ImageField requires that the `Python Imaging Library`_ is installed. 1205 1239 … … 1216 1250 * Normalizes to: A Python integer or long integer. 1217 1251 * Validates that the given value is an integer. Leading and trailing 1218 1252 whitespace is allowed, as in Python's ``int()`` function. 1253 * Error message keys: ``required``, ``invalid``, ``max_value``, 1254 ``min_value`` 1219 1255 1220 1256 Takes two optional arguments for validation, ``max_value`` and ``min_value``. 1221 1257 These control the range of values permitted in the field. … … 1228 1264 * Normalizes to: A list of Unicode objects. 1229 1265 * Validates that every value in the given list of values exists in the list 1230 1266 of choices. 1267 * Error message keys: ``required``, ``invalid_choice``, ``invalid_list`` 1231 1268 1232 1269 Takes one extra argument, ``choices``, which is an iterable (e.g., a list or 1233 1270 tuple) of 2-tuples to use as choices for this field. … … 1248 1285 * Normalizes to: A Unicode object. 1249 1286 * Validates that the given value matches against a certain regular 1250 1287 expression. 1288 * Error message keys: ``required``, ``invalid`` 1251 1289 1252 1290 Takes one required argument, ``regex``, which is a regular expression specified 1253 1291 either as a string or a compiled regular expression object. … … 1259 1297 ====================== ===================================================== 1260 1298 ``max_length`` Ensures the string has at most this many characters. 1261 1299 ``min_length`` Ensures the string has at least this many characters. 1262 ``error_message`` Error message to return for failed validation. If no1263 message is provided, a generic error message will be1264 used.1265 1300 ====================== ===================================================== 1266 1301 1302 The optional argument ``error_message`` is also accepted for backwards 1303 compatibility. The preferred way to provide an error message is to use the 1304 ``error_messages`` argument, passing a dictionary with ``'invalid'`` as a key 1305 and the error message as the value. 1306 1267 1307 ``TimeField`` 1268 1308 ~~~~~~~~~~~~~ 1269 1309 … … 1272 1312 * Normalizes to: A Python ``datetime.time`` object. 1273 1313 * Validates that the given value is either a ``datetime.time`` or string 1274 1314 formatted in a particular time format. 1315 * Error message keys: ``required``, ``invalid`` 1275 1316 1276 1317 Takes one optional argument, ``input_formats``, which is a list of formats used 1277 1318 to attempt to convert a string to a valid ``datetime.time`` object. … … 1288 1329 * Empty value: ``''`` (an empty string) 1289 1330 * Normalizes to: A Unicode object. 1290 1331 * Validates that the given value is a valid URL. 1332 * Error message keys: ``required``, ``invalid``, ``invalid_link`` 1291 1333 1292 1334 Takes the following optional arguments: 1293 1335 -
tests/regressiontests/forms/tests.py
939 939 >>> f.clean('1234567890a') 940 940 u'1234567890a' 941 941 942 Custom error messages 943 >>> e = {'required': 'REQUIRED'} 944 >>> e['min_length'] = 'LENGTH %(length)s, MIN LENGTH %(min)s' 945 >>> e['max_length'] = 'LENGTH %(length)s, MAX LENGTH %(max)s' 946 >>> f = CharField(min_length=5, max_length=10, error_messages=e) 947 >>> f.clean('') 948 Traceback (most recent call last): 949 ... 950 ValidationError: [u'REQUIRED'] 951 >>> f.clean('1234') 952 Traceback (most recent call last): 953 ... 954 ValidationError: [u'LENGTH 4, MIN LENGTH 5'] 955 >>> f.clean('12345678901') 956 Traceback (most recent call last): 957 ... 958 ValidationError: [u'LENGTH 11, MAX LENGTH 10'] 959 942 960 # IntegerField ################################################################ 943 961 944 962 >>> f = IntegerField() … … 1064 1082 ... 1065 1083 ValidationError: [u'Ensure this value is less than or equal to 20.'] 1066 1084 1085 Custom error messages 1086 >>> e = {'required': 'REQUIRED'} 1087 >>> e['invalid'] = 'INVALID' 1088 >>> e['min_value'] = 'MIN VALUE IS %s' 1089 >>> e['max_value'] = 'MAX VALUE IS %s' 1090 >>> f = IntegerField(min_value=5, max_value=10, error_messages=e) 1091 >>> f.clean('') 1092 Traceback (most recent call last): 1093 ... 1094 ValidationError: [u'REQUIRED'] 1095 >>> f.clean('abc') 1096 Traceback (most recent call last): 1097 ... 1098 ValidationError: [u'INVALID'] 1099 >>> f.clean('4') 1100 Traceback (most recent call last): 1101 ... 1102 ValidationError: [u'MIN VALUE IS 5'] 1103 >>> f.clean('11') 1104 Traceback (most recent call last): 1105 ... 1106 ValidationError: [u'MAX VALUE IS 10'] 1107 1067 1108 # FloatField ################################################################## 1068 1109 1069 1110 >>> f = FloatField() … … 1122 1163 >>> f.clean('0.5') 1123 1164 0.5 1124 1165 1166 Custom error messages 1167 >>> e = {'required': 'REQUIRED'} 1168 >>> e['invalid'] = 'INVALID' 1169 >>> e['min_value'] = 'MIN VALUE IS %s' 1170 >>> e['max_value'] = 'MAX VALUE IS %s' 1171 >>> f = FloatField(min_value=5, max_value=10, error_messages=e) 1172 >>> f.clean('') 1173 Traceback (most recent call last): 1174 ... 1175 ValidationError: [u'REQUIRED'] 1176 >>> f.clean('abc') 1177 Traceback (most recent call last): 1178 ... 1179 ValidationError: [u'INVALID'] 1180 >>> f.clean('4') 1181 Traceback (most recent call last): 1182 ... 1183 ValidationError: [u'MIN VALUE IS 5'] 1184 >>> f.clean('11') 1185 Traceback (most recent call last): 1186 ... 1187 ValidationError: [u'MAX VALUE IS 10'] 1188 1125 1189 # DecimalField ################################################################ 1126 1190 1127 1191 >>> f = DecimalField(max_digits=4, decimal_places=2) … … 1220 1284 >>> f.clean('00.50') 1221 1285 Decimal("0.50") 1222 1286 1287 Custom error messages 1288 >>> e = {'required': 'REQUIRED'} 1289 >>> e['invalid'] = 'INVALID' 1290 >>> e['min_value'] = 'MIN VALUE IS %s' 1291 >>> e['max_value'] = 'MAX VALUE IS %s' 1292 >>> e['max_digits'] = 'MAX DIGITS IS %s' 1293 >>> e['max_decimal_places'] = 'MAX DP IS %s' 1294 >>> e['max_whole_digits'] = 'MAX DIGITS BEFORE DP IS %s' 1295 >>> f = DecimalField(min_value=5, max_value=10, error_messages=e) 1296 >>> f2 = DecimalField(max_digits=4, decimal_places=2, error_messages=e) 1297 >>> f.clean('') 1298 Traceback (most recent call last): 1299 ... 1300 ValidationError: [u'REQUIRED'] 1301 >>> f.clean('abc') 1302 Traceback (most recent call last): 1303 ... 1304 ValidationError: [u'INVALID'] 1305 >>> f.clean('4') 1306 Traceback (most recent call last): 1307 ... 1308 ValidationError: [u'MIN VALUE IS 5'] 1309 >>> f.clean('11') 1310 Traceback (most recent call last): 1311 ... 1312 ValidationError: [u'MAX VALUE IS 10'] 1313 >>> f2.clean('123.45') 1314 Traceback (most recent call last): 1315 ... 1316 ValidationError: [u'MAX DIGITS IS 4'] 1317 >>> f2.clean('1.234') 1318 Traceback (most recent call last): 1319 ... 1320 ValidationError: [u'MAX DP IS 2'] 1321 >>> f2.clean('123.4') 1322 Traceback (most recent call last): 1323 ... 1324 ValidationError: [u'MAX DIGITS BEFORE DP IS 2'] 1325 1223 1326 # DateField ################################################################### 1224 1327 1225 1328 >>> import datetime … … 1297 1400 ... 1298 1401 ValidationError: [u'Enter a valid date.'] 1299 1402 1403 Custom error messages 1404 >>> e = {'required': 'REQUIRED'} 1405 >>> e['invalid'] = 'INVALID' 1406 >>> f = DateField(error_messages=e) 1407 >>> f.clean('') 1408 Traceback (most recent call last): 1409 ... 1410 ValidationError: [u'REQUIRED'] 1411 >>> f.clean('abc') 1412 Traceback (most recent call last): 1413 ... 1414 ValidationError: [u'INVALID'] 1415 1300 1416 # TimeField ################################################################### 1301 1417 1302 1418 >>> import datetime … … 1336 1452 ... 1337 1453 ValidationError: [u'Enter a valid time.'] 1338 1454 1455 Custom error messages 1456 >>> e = {'required': 'REQUIRED'} 1457 >>> e['invalid'] = 'INVALID' 1458 >>> f = TimeField(error_messages=e) 1459 >>> f.clean('') 1460 Traceback (most recent call last): 1461 ... 1462 ValidationError: [u'REQUIRED'] 1463 >>> f.clean('abc') 1464 Traceback (most recent call last): 1465 ... 1466 ValidationError: [u'INVALID'] 1467 1339 1468 # DateTimeField ############################################################### 1340 1469 1341 1470 >>> import datetime … … 1409 1538 >>> repr(f.clean('')) 1410 1539 'None' 1411 1540 1541 Custom error messages 1542 >>> e = {'required': 'REQUIRED'} 1543 >>> e['invalid'] = 'INVALID' 1544 >>> f = DateTimeField(error_messages=e) 1545 >>> f.clean('') 1546 Traceback (most recent call last): 1547 ... 1548 ValidationError: [u'REQUIRED'] 1549 >>> f.clean('abc') 1550 Traceback (most recent call last): 1551 ... 1552 ValidationError: [u'INVALID'] 1553 1412 1554 # RegexField ################################################################## 1413 1555 1414 1556 >>> f = RegexField('^\d[A-F]\d$') … … 1500 1642 ... 1501 1643 ValidationError: [u'Enter a valid value.'] 1502 1644 1645 Custom error messages 1646 >>> e = {'required': 'REQUIRED'} 1647 >>> e['invalid'] = 'INVALID' 1648 >>> e['min_length'] = 'LENGTH %(length)s, MIN LENGTH %(min)s' 1649 >>> e['max_length'] = 'LENGTH %(length)s, MAX LENGTH %(max)s' 1650 >>> f = RegexField(r'^\d+$', min_length=5, max_length=10, error_messages=e) 1651 >>> f.clean('') 1652 Traceback (most recent call last): 1653 ... 1654 ValidationError: [u'REQUIRED'] 1655 >>> f.clean('abcde') 1656 Traceback (most recent call last): 1657 ... 1658 ValidationError: [u'INVALID'] 1659 >>> f.clean('1234') 1660 Traceback (most recent call last): 1661 ... 1662 ValidationError: [u'LENGTH 4, MIN LENGTH 5'] 1663 >>> f.clean('12345678901') 1664 Traceback (most recent call last): 1665 ... 1666 ValidationError: [u'LENGTH 11, MAX LENGTH 10'] 1667 1503 1668 # EmailField ################################################################## 1504 1669 1505 1670 >>> f = EmailField() … … 1559 1724 ... 1560 1725 ValidationError: [u'Ensure this value has at most 15 characters (it has 20).'] 1561 1726 1727 Custom error messages 1728 >>> e = {'required': 'REQUIRED'} 1729 >>> e['invalid'] = 'INVALID' 1730 >>> e['min_length'] = 'LENGTH %(length)s, MIN LENGTH %(min)s' 1731 >>> e['max_length'] = 'LENGTH %(length)s, MAX LENGTH %(max)s' 1732 >>> f = EmailField(min_length=8, max_length=10, error_messages=e) 1733 >>> f.clean('') 1734 Traceback (most recent call last): 1735 ... 1736 ValidationError: [u'REQUIRED'] 1737 >>> f.clean('abcdefgh') 1738 Traceback (most recent call last): 1739 ... 1740 ValidationError: [u'INVALID'] 1741 >>> f.clean('a@b.com') 1742 Traceback (most recent call last): 1743 ... 1744 ValidationError: [u'LENGTH 7, MIN LENGTH 8'] 1745 >>> f.clean('aye@bee.com') 1746 Traceback (most recent call last): 1747 ... 1748 ValidationError: [u'LENGTH 11, MAX LENGTH 10'] 1749 1562 1750 # FileField ################################################################## 1563 1751 1564 1752 >>> f = FileField() … … 1595 1783 >>> type(f.clean({'filename': 'name', 'content':'Some File Content'})) 1596 1784 <class 'django.newforms.fields.UploadedFile'> 1597 1785 1786 Custom error messages 1787 >>> e = {'required': 'REQUIRED'} 1788 >>> e['invalid'] = 'INVALID' 1789 >>> e['missing'] = 'MISSING' 1790 >>> e['empty'] = 'EMPTY FILE' 1791 >>> f = FileField(error_messages=e) 1792 >>> f.clean('') 1793 Traceback (most recent call last): 1794 ... 1795 ValidationError: [u'REQUIRED'] 1796 >>> f.clean('abc') 1797 Traceback (most recent call last): 1798 ... 1799 ValidationError: [u'INVALID'] 1800 >>> f.clean({}) 1801 Traceback (most recent call last): 1802 ... 1803 ValidationError: [u'MISSING'] 1804 >>> f.clean({'filename': 'name', 'content':''}) 1805 Traceback (most recent call last): 1806 ... 1807 ValidationError: [u'EMPTY FILE'] 1808 1598 1809 # URLField ################################################################## 1599 1810 1600 1811 >>> f = URLField() … … 1705 1916 ... 1706 1917 ValidationError: [u'Ensure this value has at most 20 characters (it has 37).'] 1707 1918 1919 Custom error messages 1920 >>> e = {'required': 'REQUIRED'} 1921 >>> e['invalid'] = 'INVALID' 1922 >>> e['invalid_link'] = 'INVALID LINK' 1923 >>> f = URLField(verify_exists=True, error_messages=e) 1924 >>> f.clean('') 1925 Traceback (most recent call last): 1926 ... 1927 ValidationError: [u'REQUIRED'] 1928 >>> f.clean('abc.c') 1929 Traceback (most recent call last): 1930 ... 1931 ValidationError: [u'INVALID'] 1932 >>> f.clean('http://www.jfoiwjfoi23jfoijoaijfoiwjofiwjefewl.com') 1933 Traceback (most recent call last): 1934 ... 1935 ValidationError: [u'INVALID LINK'] 1936 1708 1937 # BooleanField ################################################################ 1709 1938 1710 1939 >>> f = BooleanField() … … 1743 1972 >>> f.clean('Django rocks') 1744 1973 True 1745 1974 1975 Custom error messages 1976 >>> e = {'required': 'REQUIRED'} 1977 >>> f = BooleanField(error_messages=e) 1978 >>> f.clean('') 1979 Traceback (most recent call last): 1980 ... 1981 ValidationError: [u'REQUIRED'] 1982 1746 1983 # ChoiceField ################################################################# 1747 1984 1748 1985 >>> f = ChoiceField(choices=[('1', '1'), ('2', '2')]) … … 1785 2022 ... 1786 2023 ValidationError: [u'Select a valid choice. That choice is not one of the available choices.'] 1787 2024 2025 Custom error messages 2026 >>> e = {'required': 'REQUIRED'} 2027 >>> e['invalid_choice'] = '%(value)s IS INVALID CHOICE' 2028 >>> f = ChoiceField(choices=[('a', 'aye')], error_messages=e) 2029 >>> f.clean('') 2030 Traceback (most recent call last): 2031 ... 2032 ValidationError: [u'REQUIRED'] 2033 >>> f.clean('b') 2034 Traceback (most recent call last): 2035 ... 2036 ValidationError: [u'b IS INVALID CHOICE'] 2037 1788 2038 # NullBooleanField ############################################################ 1789 2039 1790 2040 >>> f = NullBooleanField() … … 1865 2115 ... 1866 2116 ValidationError: [u'Select a valid choice. 3 is not one of the available choices.'] 1867 2117 2118 Custom error messages 2119 >>> e = {'required': 'REQUIRED'} 2120 >>> e['invalid_choice'] = '%(value)s IS INVALID CHOICE' 2121 >>> e['invalid_list'] = 'NOT A LIST' 2122 >>> f = MultipleChoiceField(choices=[('a', 'aye')], error_messages=e) 2123 >>> f.clean('') 2124 Traceback (most recent call last): 2125 ... 2126 ValidationError: [u'REQUIRED'] 2127 >>> f.clean('b') 2128 Traceback (most recent call last): 2129 ... 2130 ValidationError: [u'NOT A LIST'] 2131 >>> f.clean(['b']) 2132 Traceback (most recent call last): 2133 ... 2134 ValidationError: [u'b IS INVALID CHOICE'] 2135 1868 2136 # ComboField ################################################################## 1869 2137 1870 2138 ComboField takes a list of fields that should be used to validate a value, … … 1973 2241 ... 1974 2242 ValidationError: [u'Enter a valid date.'] 1975 2243 2244 Custom error messages 2245 >>> e = {'required': 'REQUIRED'} 2246 >>> e['invalid_date'] = 'INVALID DATE' 2247 >>> e['invalid_time'] = 'INVALID TIME' 2248 >>> f = SplitDateTimeField(error_messages=e) 2249 >>> f.clean('') 2250 Traceback (most recent call last): 2251 ... 2252 ValidationError: [u'REQUIRED'] 2253 >>> f.clean(['a', 'b']) 2254 Traceback (most recent call last): 2255 ... 2256 ValidationError: [u'INVALID DATE', u'INVALID TIME'] 2257 1976 2258 ######### 1977 2259 # Forms # 1978 2260 ######### … … 3821 4103 True 3822 4104 >>> f.cleaned_data['username'] 3823 4105 u'sirrobin' 4106 3824 4107 """ 3825 4108 3826 4109 __test__ = {