Ticket #6845: 6845-against-8090.patch
File 6845-against-8090.patch, 129.0 KB (added by , 16 years ago) |
---|
-
AUTHORS
diff --git a/AUTHORS b/AUTHORS index 967c9f7..9b7f0d1 100644
a b answer newbie questions, and generally made Django that much better: 223 223 Igor Kolar <ike@email.si> 224 224 Gasper Koren 225 225 Martin Kosír <martin@martinkosir.net> 226 Honza Kral <Honza.Kral@gmail.com> 226 227 Meir Kriheli <http://mksoft.co.il/> 227 228 Bruce Kroeze <http://coderseye.com/> 228 229 krzysiek.pawlik@silvermedia.pl -
django/contrib/admin/views/template.py
diff --git a/django/contrib/admin/views/template.py b/django/contrib/admin/views/template.py index a3b4538..89e6952 100644
a b 1 1 from django.contrib.admin.views.decorators import staff_member_required 2 from django.core import validat ors2 from django.core import validation 3 3 from django import template, oldforms 4 4 from django.template import loader 5 5 from django.shortcuts import render_to_response … … class TemplateValidator(oldforms.Manipulator): 69 69 error = e 70 70 template.builtins.remove(register) 71 71 if error: 72 raise validat ors.ValidationError, e.args72 raise validation.ValidationError, e.args -
django/contrib/auth/management/commands/createsuperuser.py
diff --git a/django/contrib/auth/management/commands/createsuperuser.py b/django/contrib/auth/management/commands/createsuperuser.py index 91e39f7..f8492f8 100644
a b class Command(BaseCommand): 39 39 if not RE_VALID_USERNAME.match(username): 40 40 raise CommandError("Invalid username. Use only letters, digits, and underscores") 41 41 try: 42 validators. isValidEmail(email, None)42 validators.validate_email(email) 43 43 except validators.ValidationError: 44 44 raise CommandError("Invalid email address.") 45 45 -
django/contrib/auth/models.py
diff --git a/django/contrib/auth/models.py b/django/contrib/auth/models.py index 3ea184a..4c381c9 100644
a b class User(models.Model): 131 131 132 132 Username and password are required. Other fields are optional. 133 133 """ 134 username = models.CharField(_('username'), max_length=30, unique=True, validator_list=[validators. isAlphaNumeric], help_text=_("Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores)."))134 username = models.CharField(_('username'), max_length=30, unique=True, validator_list=[validators.validate_alpha_numeric], help_text=_("Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores).")) 135 135 first_name = models.CharField(_('first name'), max_length=30, blank=True) 136 136 last_name = models.CharField(_('last name'), max_length=30, blank=True) 137 137 email = models.EmailField(_('e-mail address'), blank=True) -
django/contrib/comments/views/comments.py
diff --git a/django/contrib/comments/views/comments.py b/django/contrib/comments/views/comments.py index ba59cba..87d60f9 100644
a b 1 1 import base64 2 2 import datetime 3 3 4 from django. coreimport validators4 from django.oldforms import validators 5 5 from django import oldforms 6 6 from django.core.mail import mail_admins, mail_managers 7 7 from django.http import Http404 -
django/contrib/flatpages/models.py
diff --git a/django/contrib/flatpages/models.py b/django/contrib/flatpages/models.py index 466425c..c69be18 100644
a b from django.utils.translation import ugettext_lazy as _ 5 5 6 6 7 7 class FlatPage(models.Model): 8 url = models.CharField(_('URL'), max_length=100, validator_list=[validators. isAlphaNumericURL], db_index=True,8 url = models.CharField(_('URL'), max_length=100, validator_list=[validators.validate_alpha_numeric], db_index=True, 9 9 help_text=_("Example: '/about/contact/'. Make sure to have leading and trailing slashes.")) 10 10 title = models.CharField(_('title'), max_length=200) 11 11 content = models.TextField(_('content'), blank=True) -
django/contrib/localflavor/br/forms.py
diff --git a/django/contrib/localflavor/br/forms.py b/django/contrib/localflavor/br/forms.py index 6d0a038..27505b2 100644
a b class BRPhoneNumberField(Field): 31 31 } 32 32 33 33 def clean(self, value): 34 super(BRPhoneNumberField, self).clean(value)34 value = super(BRPhoneNumberField, self).clean(value) 35 35 if value in EMPTY_VALUES: 36 36 return u'' 37 value = re.sub('(\(|\)|\s+)', '', smart_unicode(value))37 value = re.sub('(\(|\)|\s+)', '', value) 38 38 m = phone_digits_re.search(value) 39 39 if m: 40 40 return u'%s-%s-%s' % (m.group(1), m.group(2), m.group(3)) -
django/contrib/localflavor/fi/forms.py
diff --git a/django/contrib/localflavor/fi/forms.py b/django/contrib/localflavor/fi/forms.py index 2b82a79..f9d9125 100644
a b class FISocialSecurityNumber(Field): 29 29 } 30 30 31 31 def clean(self, value): 32 super(FISocialSecurityNumber, self).clean(value) 33 if value in EMPTY_VALUES: 32 # changed not to throw UnicodeDecode error when passed invalid data 33 # I think this SHOULD call super.clean, which would mean ^^^ 34 if self.required and value in EMPTY_VALUES: 35 raise ValidationError(self.error_messages['required']) 36 elif value in EMPTY_VALUES: 34 37 return u'' 35 38 36 39 checkmarks = "0123456789ABCDEFHJKLMNPRSTUVWXY" -
django/contrib/localflavor/jp/forms.py
diff --git a/django/contrib/localflavor/jp/forms.py b/django/contrib/localflavor/jp/forms.py index c86dbaf..40b1407 100644
a b 2 2 JP-specific Form helpers 3 3 """ 4 4 5 from django.core import validators6 from django.forms import ValidationError7 5 from django.utils.translation import ugettext_lazy as _ 8 6 from django.forms.fields import RegexField, Select 9 7 -
django/core/exceptions.py
diff --git a/django/core/exceptions.py b/django/core/exceptions.py index e5df8ca..fb6634f 100644
a b class FieldError(Exception): 32 32 """Some kind of problem with a model field.""" 33 33 pass 34 34 35 NON_FIELD_ERRORS = '__all__' 36 class ValidationError(Exception): 37 def __init__(self, message): 38 """ 39 ValidationError can be passed any object that can be printed (usually 40 a string) or a list of objects. 41 """ 42 from django.utils.encoding import force_unicode 43 if hasattr(message, '__iter__'): 44 self.messages = [force_unicode(msg) for msg in message] 45 else: 46 message = force_unicode(message) 47 self.messages = [message] 48 49 if isinstance(message, dict): 50 self.message_dict = message 51 52 def __str__(self): 53 # This is needed because, without a __str__(), printing an exception 54 # instance would result in this: 55 # AttributeError: ValidationError instance has no attribute 'args' 56 # See http://www.python.org/doc/current/tut/node10.html#handling 57 from django.utils.encoding import force_unicode 58 if hasattr(self, 'message_dict'): 59 return repr(self.message_dict) 60 return repr([force_unicode(e) for e in self.messages]) -
django/core/validators.py
diff --git a/django/core/validators.py b/django/core/validators.py index f94db40..62af2eb 100644
a b 1 1 """ 2 2 A library of validators that return None and raise ValidationError when the 3 3 provided data isn't valid. 4 5 Validators may be callable classes, and they may have an 'always_test'6 attribute. If an 'always_test' attribute exists (regardless of value), the7 validator will *always* be run, regardless of whether its associated8 form field is required.9 4 """ 10 5 11 import urllib212 6 import re 13 try: 14 from decimal import Decimal, DecimalException 15 except ImportError: 16 from django.utils._decimal import Decimal, DecimalException # Python 2.3 7 import urllib2 17 8 18 9 from django.conf import settings 19 from django.utils.translation import ugettext as _, ugettext_lazy, ungettext 20 from django.utils.functional import Promise, lazy 21 from django.utils.encoding import force_unicode, smart_str 10 from django.utils.encoding import smart_str 11 from django.utils.translation import ugettext as _ 12 from django.core.exceptions import ValidationError 13 14 def regexp_validator(regexp, message_codes, message): 15 if isinstance(regexp, basestring): 16 regexp = re.compile(regexp) 17 18 def _regexp_validator(value, message_dict={}): 19 if not regexp.search(value): 20 for m in message_codes: 21 if m in message_dict: 22 mess = message_dict[m] 23 break 24 else: 25 mess = _(message) 26 27 raise ValidationError, mess 28 return _regexp_validator 22 29 23 _datere = r'\d{4}-\d{1,2}-\d{1,2}'24 _timere = r'(?:[01]?[0-9]|2[0-3]):[0-5][0-9](?::[0-5][0-9])?'25 alnum_re = re.compile(r'^\w+$')26 alnumurl_re = re.compile(r'^[-\w/]+$')27 ansi_date_re = re.compile('^%s$' % _datere)28 ansi_time_re = re.compile('^%s$' % _timere)29 ansi_datetime_re = re.compile('^%s %s$' % (_datere, _timere))30 30 email_re = re.compile( 31 31 r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*" # dot-atom 32 32 r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*"' # quoted-string 33 33 r')@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$', re.IGNORECASE) # domain 34 integer_re = re.compile(r'^-?\d+$')35 ip4_re = re.compile(r'^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$')36 phone_re = re.compile(r'^[A-PR-Y0-9]{3}-[A-PR-Y0-9]{3}-[A-PR-Y0-9]{4}$', re.IGNORECASE)37 slug_re = re.compile(r'^[-\w]+$')38 url_re = re.compile(r'^https?://\S+$')39 40 lazy_inter = lazy(lambda a,b: force_unicode(a) % b, unicode)41 42 class ValidationError(Exception):43 def __init__(self, message):44 "ValidationError can be passed a string or a list."45 if isinstance(message, list):46 self.messages = [force_unicode(msg) for msg in message]47 else:48 assert isinstance(message, (basestring, Promise)), ("%s should be a string" % repr(message))49 self.messages = [force_unicode(message)]50 51 def __str__(self):52 # This is needed because, without a __str__(), printing an exception53 # instance would result in this:54 # AttributeError: ValidationError instance has no attribute 'args'55 # See http://www.python.org/doc/current/tut/node10.html#handling56 return str(self.messages)57 58 class CriticalValidationError(Exception):59 def __init__(self, message):60 "ValidationError can be passed a string or a list."61 if isinstance(message, list):62 self.messages = [force_unicode(msg) for msg in message]63 else:64 assert isinstance(message, (basestring, Promise)), ("'%s' should be a string" % message)65 self.messages = [force_unicode(message)]66 67 def __str__(self):68 return str(self.messages)69 70 def isAlphaNumeric(field_data, all_data):71 if not alnum_re.search(field_data):72 raise ValidationError, _("This value must contain only letters, numbers and underscores.")73 74 def isAlphaNumericURL(field_data, all_data):75 if not alnumurl_re.search(field_data):76 raise ValidationError, _("This value must contain only letters, numbers, underscores, dashes or slashes.")77 78 def isSlug(field_data, all_data):79 if not slug_re.search(field_data):80 raise ValidationError, _("This value must contain only letters, numbers, underscores or hyphens.")81 82 def isLowerCase(field_data, all_data):83 if field_data.lower() != field_data:84 raise ValidationError, _("Uppercase letters are not allowed here.")85 34 86 def isUpperCase(field_data, all_data): 87 if field_data.upper() != field_data: 88 raise ValidationError, _("Lowercase letters are not allowed here.") 35 validate_email = regexp_validator( 36 email_re, ('invalid_email','invalid',), 37 'Enter a valid e-mail address.' 38 ) 89 39 90 def isCommaSeparatedIntegerList(field_data, all_data): 91 for supposed_int in field_data.split(','): 92 try: 93 int(supposed_int) 94 except ValueError: 95 raise ValidationError, _("Enter only digits separated by commas.") 40 validate_alpha_numeric_URL = regexp_validator( 41 re.compile(r'^[-\w/]+$'), ('invalid',), 42 "This value must contain only letters, numbers, underscores, dashes or slashes." 43 ) 96 44 97 def isCommaSeparatedEmailList(field_data, all_data):98 """99 Checks that field_data is a string of e-mail addresses separated by commas.100 Blank field_data values will not throw a validation error, and whitespace101 is allowed around the commas.102 """103 for supposed_email in field_data.split(','):104 try:105 isValidEmail(supposed_email.strip(), '')106 except ValidationError:107 raise ValidationError, _("Enter valid e-mail addresses separated by commas.")108 109 def isValidIPAddress4(field_data, all_data):110 if not ip4_re.search(field_data):111 raise ValidationError, _("Please enter a valid IP address.")112 45 113 def isNotEmpty(field_data, all_data): 114 if field_data.strip() == '': 115 raise ValidationError, _("Empty values are not allowed here.") 46 validate_alpha_numeric = regexp_validator( 47 re.compile(r'^\w+$'), ('invalid',), 48 "This value must contain only letters, numbers and underscores." 49 ) 116 50 117 def isOnlyDigits(field_data, all_data): 118 if not field_data.isdigit(): 119 raise ValidationError, _("Non-numeric characters aren't allowed here.") 51 validate_ip_address4 = regexp_validator( 52 re.compile(r'^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$'), ('invalid',), 53 "Enter a valid IPv4 address." 54 ) 120 55 121 def isNotOnlyDigits(field_data, all_data): 122 if field_data.isdigit(): 123 raise ValidationError, _("This value can't be comprised solely of digits.") 56 validate_phone_number = regexp_validator( 57 re.compile(r'^[A-PR-Y0-9]{3}-[A-PR-Y0-9]{3}-[A-PR-Y0-9]{4}$', re.IGNORECASE), ('invalid',), 58 'Phone numbers must be in XXX-XXX-XXXX format.' 59 ) 124 60 125 def isInteger(field_data, all_data): 126 # This differs from isOnlyDigits because this accepts the negative sign127 if not integer_re.search(field_data):128 raise ValidationError, _("Enter a whole number.")61 validate_slug = regexp_validator( 62 re.compile(r'^[-\w]+$'), ('invalid',), 63 "This value must contain only letters, numbers, underscores or hyphens." 64 ) 129 65 130 def isOnlyLetters(field_data, all_data): 131 if not field_data.isalpha(): 132 raise ValidationError, _("Only alphabetical characters are allowed here.") 66 _datere = r'\d{4}-\d{1,2}-\d{1,2}' 67 validate_ansi_date_format = regexp_validator( 68 re.compile('^%s$' % _datere), ('invalid',), 69 'Enter a valid date in YYYY-MM-DD format.' 70 ) 133 71 134 def _isValidDate(date_string): 135 """ 136 A helper function used by isValidANSIDate and isValidANSIDatetime to 137 check if the date is valid. The date string is assumed to already be in 138 YYYY-MM-DD format. 139 """ 72 _timere = r'(?:[01]?[0-9]|2[0-3]):[0-5][0-9](?::[0-5][0-9])?' 73 validate_ansi_time = regexp_validator( 74 re.compile('^%s$' % _timere), ('invalid',), 75 'Enter a valid time in HH:MM format.' 76 ) 77 78 validate_ansi_datetime_format = regexp_validator( 79 re.compile('^%s %s$' % (_datere, _timere)), ('invalid',), 80 'Enter a valid date/time in YYYY-MM-DD HH:MM format.' 81 ) 82 83 validate_integer = regexp_validator( 84 re.compile(r'^-?\d+$'), ('invalid',), 85 "Enter a whole number." 86 ) 87 88 def validate_correct_ansi_date(value, message_dict={}): 140 89 from datetime import date 141 90 # Could use time.strptime here and catch errors, but datetime.date below 142 91 # produces much friendlier error messages. 143 year, month, day = map(int, date_string.split('-')) 92 year, month, day = map(int, value.split('-')) 93 # This check is needed because strftime is used when saving the date 94 # value to the database, and strftime requires that the year be >=1900. 95 if year < 1900: 96 raise ValidationError, _('Year must be 1900 or later.') 144 97 try: 145 98 date(year, month, day) 146 99 except ValueError, e: 147 100 msg = _('Invalid date: %s') % _(str(e)) 148 raise ValidationError, msg149 101 150 def isValidANSIDate(field_data, all_data): 151 if not ansi_date_re.search(field_data): 152 raise ValidationError, _('Enter a valid date in YYYY-MM-DD format.') 153 _isValidDate(field_data) 102 def validate_ansi_date(value, message_dict={}): 103 validate_ansi_date_format(value, message_dict) 104 validate_correct_ansi_date(value, message_dict) 154 105 155 def isValidANSITime(field_data, all_data):156 if not ansi_time_re.search(field_data):157 raise ValidationError, _('Enter a valid time in HH:MM format.')106 def validate_ansi_datetime(value, message_dict={}): 107 validate_ansi_datetime_format(value, message_dict) 108 validate_correct_ansi_date(value.split()[0], message_dict) 158 109 159 def isValidANSIDatetime(field_data, all_data): 160 if not ansi_datetime_re.search(field_data): 161 raise ValidationError, _('Enter a valid date/time in YYYY-MM-DD HH:MM format.') 162 _isValidDate(field_data.split()[0]) 110 def validate_not_empty(value, message_dict={}): 111 if value.strip() == '': 112 raise ValidationError, _("Empty values are not allowed here.") 163 113 164 def isValidEmail(field_data, all_data):165 if not email_re.search(field_data):166 raise ValidationError, _( 'Enter a valid e-mail address.')114 def validate_digits_only(value, message_dict={}): 115 if not value.isdigit(): 116 raise ValidationError, _("Non-numeric characters aren't allowed here.") 167 117 168 def isValidImage(field_data, all_data): 169 """ 170 Checks that the file-upload field data contains a valid image (GIF, JPG, 171 PNG, possibly others -- whatever the Python Imaging Library supports). 172 """ 173 from PIL import Image 174 from cStringIO import StringIO 175 try: 176 content = field_data.read() 177 except TypeError: 178 raise ValidationError, _("No file was submitted. Check the encoding type on the form.") 179 try: 180 # load() is the only method that can spot a truncated JPEG, 181 # but it cannot be called sanely after verify() 182 trial_image = Image.open(StringIO(content)) 183 trial_image.load() 184 # verify() is the only method that can spot a corrupt PNG, 185 # but it must be called immediately after the constructor 186 trial_image = Image.open(StringIO(content)) 187 trial_image.verify() 188 except Exception: # Python Imaging Library doesn't recognize it as an image 189 raise ValidationError, _("Upload a valid image. The file you uploaded was either not an image or a corrupted image.") 190 191 def isValidImageURL(field_data, all_data): 192 uc = URLMimeTypeCheck(('image/jpeg', 'image/gif', 'image/png')) 193 try: 194 uc(field_data, all_data) 195 except URLMimeTypeCheck.InvalidContentType: 196 raise ValidationError, _("The URL %s does not point to a valid image.") % field_data 118 def validate_not_digits_only(value, message_dict={}): 119 if value.isdigit(): 120 raise ValidationError, _("This value can't be comprised solely of digits.") 197 121 198 def isValidPhone(field_data, all_data):199 if not phone_re.search(field_data):200 raise ValidationError, _( 'Phone numbers must be in XXX-XXX-XXXX format. "%s" is invalid.') % field_data122 def validate_letters_only(value, message_dict={}): 123 if not value.isalpha(): 124 raise ValidationError, _("Only alphabetical characters are allowed here.") 201 125 202 def isValidQuicktimeVideoURL(field_data, all_data): 203 "Checks that the given URL is a video that can be played by QuickTime (qt, mpeg)" 204 uc = URLMimeTypeCheck(('video/quicktime', 'video/mpeg',)) 205 try: 206 uc(field_data, all_data) 207 except URLMimeTypeCheck.InvalidContentType: 208 raise ValidationError, _("The URL %s does not point to a valid QuickTime video.") % field_data 126 def validate_lower(value, message_dict={}): 127 if value.lower() != value: 128 raise ValidationError, _("Uppercase letters are not allowed here.") 209 129 210 def isValidURL(field_data, all_data):211 if not url_re.search(field_data):212 raise ValidationError, _(" A valid URL is required.")130 def validate_upper(value, message_dict={}): 131 if value.upper() != value: 132 raise ValidationError, _("Lowercase letters are not allowed here.") 213 133 214 def isValidHTML(field_data, all_data): 215 import urllib, urllib2 216 try: 217 u = urllib2.urlopen('http://validator.w3.org/check', urllib.urlencode({'fragment': field_data, 'output': 'xml'})) 218 except: 219 # Validator or Internet connection is unavailable. Fail silently. 220 return 221 html_is_valid = (u.headers.get('x-w3c-validator-status', 'Invalid') == 'Valid') 222 if html_is_valid: 223 return 224 from xml.dom.minidom import parseString 225 error_messages = [e.firstChild.wholeText for e in parseString(u.read()).getElementsByTagName('messages')[0].getElementsByTagName('msg')] 226 raise ValidationError, _("Valid HTML is required. Specific errors are:\n%s") % "\n".join(error_messages) 227 228 def isWellFormedXml(field_data, all_data): 229 from xml.dom.minidom import parseString 230 try: 231 parseString(field_data) 232 except Exception, e: # Naked except because we're not sure what will be thrown 233 raise ValidationError, _("Badly formed XML: %s") % str(e) 134 def validate_comma_separated_integer_list(value, message_dict={}): 135 for supposed_integer in value.split(','): 136 try: 137 validate_integer(supposed_integer.strip()) 138 except ValidationError: 139 raise ValidationError, _("Enter valid integers separated by commas.") 234 140 235 def isWellFormedXmlFragment(field_data, all_data): 236 isWellFormedXml('<root>%s</root>' % field_data, all_data) 141 def validate_comma_separated_email_list(value, message_dict={}): 142 """ 143 Checks that value is a string of e-mail addresses separated by commas. 144 Blank value values will not throw a validation error, and whitespace 145 is allowed around the commas. 146 """ 147 for supposed_email in value.split(','): 148 try: 149 validate_email(supposed_email.strip()) 150 except ValidationError: 151 raise ValidationError, _("Enter valid e-mail addresses separated by commas.") 237 152 238 def isExistingURL(field_data, all_data):153 def validate_existing_url(value, message_dict={}): 239 154 try: 240 155 headers = { 241 156 "Accept" : "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5", … … def isExistingURL(field_data, all_data): 244 159 "Connection" : "close", 245 160 "User-Agent": settings.URL_VALIDATOR_USER_AGENT 246 161 } 247 req = urllib2.Request( field_data,None, headers)162 req = urllib2.Request(value,None, headers) 248 163 u = urllib2.urlopen(req) 249 164 except ValueError: 250 raise ValidationError, _("Invalid URL: %s") % field_data165 raise ValidationError, message_dict.get('invalid', _("Invalid URL: %s") % value) 251 166 except urllib2.HTTPError, e: 252 167 # 401s are valid; they just mean authorization is required. 253 168 # 301 and 302 are redirects; they just mean look somewhere else. 254 169 if str(e.code) not in ('401','301','302'): 255 raise ValidationError, _("The URL %s is a broken link.") % field_data170 raise ValidationError, message_dict.get('invalid_link', _("This URL appears to be a broken link.")) 256 171 except: # urllib2.URLError, httplib.InvalidURL, etc. 257 raise ValidationError, _("The URL %s is a broken link.") % field_data 258 259 def isValidUSState(field_data, all_data): 260 "Checks that the given string is a valid two-letter U.S. state abbreviation" 261 states = ['AA', 'AE', 'AK', 'AL', 'AP', 'AR', 'AS', 'AZ', 'CA', 'CO', 'CT', 'DC', 'DE', 'FL', 'FM', 'GA', 'GU', 'HI', 'IA', 'ID', 'IL', 'IN', 'KS', 'KY', 'LA', 'MA', 'MD', 'ME', 'MH', 'MI', 'MN', 'MO', 'MP', 'MS', 'MT', 'NC', 'ND', 'NE', 'NH', 'NJ', 'NM', 'NV', 'NY', 'OH', 'OK', 'OR', 'PA', 'PR', 'PW', 'RI', 'SC', 'SD', 'TN', 'TX', 'UT', 'VA', 'VI', 'VT', 'WA', 'WI', 'WV', 'WY'] 262 if field_data.upper() not in states: 263 raise ValidationError, _("Enter a valid U.S. state abbreviation.") 264 265 def hasNoProfanities(field_data, all_data): 266 """ 267 Checks that the given string has no profanities in it. This does a simple 268 check for whether each profanity exists within the string, so 'fuck' will 269 catch 'motherfucker' as well. Raises a ValidationError such as: 270 Watch your mouth! The words "f--k" and "s--t" are not allowed here. 271 """ 272 field_data = field_data.lower() # normalize 273 words_seen = [w for w in settings.PROFANITIES_LIST if w in field_data] 274 if words_seen: 275 from django.utils.text import get_text_list 276 plural = len(words_seen) 277 raise ValidationError, ungettext("Watch your mouth! The word %s is not allowed here.", 278 "Watch your mouth! The words %s are not allowed here.", plural) % \ 279 get_text_list(['"%s%s%s"' % (i[0], '-'*(len(i)-2), i[-1]) for i in words_seen], _('and')) 280 281 class AlwaysMatchesOtherField(object): 282 def __init__(self, other_field_name, error_message=None): 283 self.other = other_field_name 284 self.error_message = error_message or lazy_inter(ugettext_lazy("This field must match the '%s' field."), self.other) 285 self.always_test = True 286 287 def __call__(self, field_data, all_data): 288 if field_data != all_data[self.other]: 289 raise ValidationError, self.error_message 290 291 class ValidateIfOtherFieldEquals(object): 292 def __init__(self, other_field, other_value, validator_list): 293 self.other_field, self.other_value = other_field, other_value 294 self.validator_list = validator_list 295 self.always_test = True 296 297 def __call__(self, field_data, all_data): 298 if self.other_field in all_data and all_data[self.other_field] == self.other_value: 299 for v in self.validator_list: 300 v(field_data, all_data) 301 302 class RequiredIfOtherFieldNotGiven(object): 303 def __init__(self, other_field_name, error_message=ugettext_lazy("Please enter something for at least one field.")): 304 self.other, self.error_message = other_field_name, error_message 305 self.always_test = True 306 307 def __call__(self, field_data, all_data): 308 if not all_data.get(self.other, False) and not field_data: 309 raise ValidationError, self.error_message 310 311 class RequiredIfOtherFieldsGiven(object): 312 def __init__(self, other_field_names, error_message=ugettext_lazy("Please enter both fields or leave them both empty.")): 313 self.other, self.error_message = other_field_names, error_message 314 self.always_test = True 315 316 def __call__(self, field_data, all_data): 317 for field in self.other: 318 if all_data.get(field, False) and not field_data: 319 raise ValidationError, self.error_message 320 321 class RequiredIfOtherFieldGiven(RequiredIfOtherFieldsGiven): 322 "Like RequiredIfOtherFieldsGiven, but takes a single field name instead of a list." 323 def __init__(self, other_field_name, error_message=ugettext_lazy("Please enter both fields or leave them both empty.")): 324 RequiredIfOtherFieldsGiven.__init__(self, [other_field_name], error_message) 325 326 class RequiredIfOtherFieldEquals(object): 327 def __init__(self, other_field, other_value, error_message=None, other_label=None): 328 self.other_field = other_field 329 self.other_value = other_value 330 other_label = other_label or other_value 331 self.error_message = error_message or lazy_inter(ugettext_lazy("This field must be given if %(field)s is %(value)s"), { 332 'field': other_field, 'value': other_label}) 333 self.always_test = True 334 335 def __call__(self, field_data, all_data): 336 if self.other_field in all_data and all_data[self.other_field] == self.other_value and not field_data: 337 raise ValidationError(self.error_message) 338 339 class RequiredIfOtherFieldDoesNotEqual(object): 340 def __init__(self, other_field, other_value, other_label=None, error_message=None): 341 self.other_field = other_field 342 self.other_value = other_value 343 other_label = other_label or other_value 344 self.error_message = error_message or lazy_inter(ugettext_lazy("This field must be given if %(field)s is not %(value)s"), { 345 'field': other_field, 'value': other_label}) 346 self.always_test = True 347 348 def __call__(self, field_data, all_data): 349 if self.other_field in all_data and all_data[self.other_field] != self.other_value and not field_data: 350 raise ValidationError(self.error_message) 351 352 class IsLessThanOtherField(object): 353 def __init__(self, other_field_name, error_message): 354 self.other, self.error_message = other_field_name, error_message 355 356 def __call__(self, field_data, all_data): 357 if field_data > all_data[self.other]: 358 raise ValidationError, self.error_message 359 360 class UniqueAmongstFieldsWithPrefix(object): 361 def __init__(self, field_name, prefix, error_message): 362 self.field_name, self.prefix = field_name, prefix 363 self.error_message = error_message or ugettext_lazy("Duplicate values are not allowed.") 364 365 def __call__(self, field_data, all_data): 366 for field_name, value in all_data.items(): 367 if field_name != self.field_name and value == field_data: 368 raise ValidationError, self.error_message 369 370 class NumberIsInRange(object): 371 """ 372 Validator that tests if a value is in a range (inclusive). 373 """ 374 def __init__(self, lower=None, upper=None, error_message=''): 375 self.lower, self.upper = lower, upper 376 if not error_message: 377 if lower and upper: 378 self.error_message = _("This value must be between %(lower)s and %(upper)s.") % {'lower': lower, 'upper': upper} 379 elif lower: 380 self.error_message = _("This value must be at least %s.") % lower 381 elif upper: 382 self.error_message = _("This value must be no more than %s.") % upper 383 else: 384 self.error_message = error_message 385 386 def __call__(self, field_data, all_data): 387 # Try to make the value numeric. If this fails, we assume another 388 # validator will catch the problem. 389 try: 390 val = float(field_data) 391 except ValueError: 392 return 393 394 # Now validate 395 if self.lower and self.upper and (val < self.lower or val > self.upper): 396 raise ValidationError(self.error_message) 397 elif self.lower and val < self.lower: 398 raise ValidationError(self.error_message) 399 elif self.upper and val > self.upper: 400 raise ValidationError(self.error_message) 401 402 class IsAPowerOf(object): 403 """ 404 Usage: If you create an instance of the IsPowerOf validator: 405 v = IsAPowerOf(2) 406 407 The following calls will succeed: 408 v(4, None) 409 v(8, None) 410 v(16, None) 411 412 But this call: 413 v(17, None) 414 will raise "django.core.validators.ValidationError: ['This value must be a power of 2.']" 415 """ 416 def __init__(self, power_of): 417 self.power_of = power_of 418 419 def __call__(self, field_data, all_data): 420 from math import log 421 val = log(int(field_data)) / log(self.power_of) 422 if val != int(val): 423 raise ValidationError, _("This value must be a power of %s.") % self.power_of 424 425 class IsValidDecimal(object): 426 def __init__(self, max_digits, decimal_places): 427 self.max_digits, self.decimal_places = max_digits, decimal_places 428 429 def __call__(self, field_data, all_data): 430 try: 431 val = Decimal(field_data) 432 except DecimalException: 433 raise ValidationError, _("Please enter a valid decimal number.") 434 435 pieces = str(val).lstrip("-").split('.') 436 decimals = (len(pieces) == 2) and len(pieces[1]) or 0 437 digits = len(pieces[0]) 438 439 if digits + decimals > self.max_digits: 440 raise ValidationError, ungettext("Please enter a valid decimal number with at most %s total digit.", 441 "Please enter a valid decimal number with at most %s total digits.", self.max_digits) % self.max_digits 442 if digits > (self.max_digits - self.decimal_places): 443 raise ValidationError, ungettext( "Please enter a valid decimal number with a whole part of at most %s digit.", 444 "Please enter a valid decimal number with a whole part of at most %s digits.", str(self.max_digits-self.decimal_places)) % str(self.max_digits-self.decimal_places) 445 if decimals > self.decimal_places: 446 raise ValidationError, ungettext("Please enter a valid decimal number with at most %s decimal place.", 447 "Please enter a valid decimal number with at most %s decimal places.", self.decimal_places) % self.decimal_places 448 449 def isValidFloat(field_data, all_data): 450 data = smart_str(field_data) 451 try: 452 float(data) 453 except ValueError: 454 raise ValidationError, _("Please enter a valid floating point number.") 455 456 class HasAllowableSize(object): 457 """ 458 Checks that the file-upload field data is a certain size. min_size and 459 max_size are measurements in bytes. 460 """ 461 def __init__(self, min_size=None, max_size=None, min_error_message=None, max_error_message=None): 462 self.min_size, self.max_size = min_size, max_size 463 self.min_error_message = min_error_message or lazy_inter(ugettext_lazy("Make sure your uploaded file is at least %s bytes big."), min_size) 464 self.max_error_message = max_error_message or lazy_inter(ugettext_lazy("Make sure your uploaded file is at most %s bytes big."), max_size) 465 466 def __call__(self, field_data, all_data): 467 try: 468 content = field_data.read() 469 except TypeError: 470 raise ValidationError, ugettext_lazy("No file was submitted. Check the encoding type on the form.") 471 if self.min_size is not None and len(content) < self.min_size: 472 raise ValidationError, self.min_error_message 473 if self.max_size is not None and len(content) > self.max_size: 474 raise ValidationError, self.max_error_message 475 476 class MatchesRegularExpression(object): 477 """ 478 Checks that the field matches the given regular-expression. The regex 479 should be in string format, not already compiled. 480 """ 481 def __init__(self, regexp, error_message=ugettext_lazy("The format for this field is wrong.")): 482 self.regexp = re.compile(regexp) 483 self.error_message = error_message 484 485 def __call__(self, field_data, all_data): 486 if not self.regexp.search(field_data): 487 raise ValidationError(self.error_message) 488 489 class AnyValidator(object): 490 """ 491 This validator tries all given validators. If any one of them succeeds, 492 validation passes. If none of them succeeds, the given message is thrown 493 as a validation error. The message is rather unspecific, so it's best to 494 specify one on instantiation. 495 """ 496 def __init__(self, validator_list=None, error_message=ugettext_lazy("This field is invalid.")): 497 if validator_list is None: validator_list = [] 498 self.validator_list = validator_list 499 self.error_message = error_message 500 for v in validator_list: 501 if hasattr(v, 'always_test'): 502 self.always_test = True 503 504 def __call__(self, field_data, all_data): 505 for v in self.validator_list: 506 try: 507 v(field_data, all_data) 508 return 509 except ValidationError, e: 510 pass 511 raise ValidationError(self.error_message) 172 raise ValidationError, message_dict.get('invalid_link', _("This URL appears to be a broken link.")) 512 173 513 174 class URLMimeTypeCheck(object): 514 175 "Checks that the provided URL points to a document with a listed mime type" … … class URLMimeTypeCheck(object): 520 181 def __init__(self, mime_type_list): 521 182 self.mime_type_list = mime_type_list 522 183 523 def __call__(self, field_data, all_data): 524 import urllib2 525 try: 526 isValidURL(field_data, all_data) 527 except ValidationError: 528 raise 184 def __call__(self, value, message_dict={}): 185 validate_existing_url(value) 529 186 try: 530 info = urllib2.urlopen( field_data).info()187 info = urllib2.urlopen(value).info() 531 188 except (urllib2.HTTPError, urllib2.URLError): 532 raise URLMimeTypeCheck.CouldNotRetrieve, _("Could not retrieve anything from %s.") % field_data189 raise URLMimeTypeCheck.CouldNotRetrieve, _("Could not retrieve anything from %s.") % value 533 190 content_type = info['content-type'] 534 191 if content_type not in self.mime_type_list: 535 192 raise URLMimeTypeCheck.InvalidContentType, _("The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'.") % { 536 'url': field_data, 'contenttype': content_type} 537 538 class RelaxNGCompact(object): 539 "Validate against a Relax NG compact schema" 540 def __init__(self, schema_path, additional_root_element=None): 541 self.schema_path = schema_path 542 self.additional_root_element = additional_root_element 543 544 def __call__(self, field_data, all_data): 545 import os, tempfile 546 if self.additional_root_element: 547 field_data = '<%(are)s>%(data)s\n</%(are)s>' % { 548 'are': self.additional_root_element, 549 'data': field_data 550 } 551 filename = tempfile.mktemp() # Insecure, but nothing else worked 552 fp = open(filename, 'w') 553 fp.write(field_data) 554 fp.close() 555 if not os.path.exists(settings.JING_PATH): 556 raise Exception, "%s not found!" % settings.JING_PATH 557 p = os.popen('%s -c %s %s' % (settings.JING_PATH, self.schema_path, filename)) 558 errors = [line.strip() for line in p.readlines()] 559 p.close() 560 os.unlink(filename) 561 display_errors = [] 562 lines = field_data.split('\n') 563 for error in errors: 564 ignored, line, level, message = error.split(':', 3) 565 # Scrape the Jing error messages to reword them more nicely. 566 m = re.search(r'Expected "(.*?)" to terminate element starting on line (\d+)', message) 567 if m: 568 display_errors.append(_('Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with "%(start)s".)') % \ 569 {'tag':m.group(1).replace('/', ''), 'line':m.group(2), 'start':lines[int(m.group(2)) - 1][:30]}) 570 continue 571 if message.strip() == 'text not allowed here': 572 display_errors.append(_('Some text starting on line %(line)s is not allowed in that context. (Line starts with "%(start)s".)') % \ 573 {'line':line, 'start':lines[int(line) - 1][:30]}) 574 continue 575 m = re.search(r'\s*attribute "(.*?)" not allowed at this point; ignored', message) 576 if m: 577 display_errors.append(_('"%(attr)s" on line %(line)s is an invalid attribute. (Line starts with "%(start)s".)') % \ 578 {'attr':m.group(1), 'line':line, 'start':lines[int(line) - 1][:30]}) 579 continue 580 m = re.search(r'\s*unknown element "(.*?)"', message) 581 if m: 582 display_errors.append(_('"<%(tag)s>" on line %(line)s is an invalid tag. (Line starts with "%(start)s".)') % \ 583 {'tag':m.group(1), 'line':line, 'start':lines[int(line) - 1][:30]}) 584 continue 585 if message.strip() == 'required attributes missing': 586 display_errors.append(_('A tag on line %(line)s is missing one or more required attributes. (Line starts with "%(start)s".)') % \ 587 {'line':line, 'start':lines[int(line) - 1][:30]}) 588 continue 589 m = re.search(r'\s*bad value for attribute "(.*?)"', message) 590 if m: 591 display_errors.append(_('The "%(attr)s" attribute on line %(line)s has an invalid value. (Line starts with "%(start)s".)') % \ 592 {'attr':m.group(1), 'line':line, 'start':lines[int(line) - 1][:30]}) 593 continue 594 # Failing all those checks, use the default error message. 595 display_error = 'Line %s: %s [%s]' % (line, message, level.strip()) 596 display_errors.append(display_error) 597 if len(display_errors) > 0: 598 raise ValidationError, display_errors 193 'url': value, 'contenttype': content_type} 194 195 def validate_image_url(value, message_dict={}): 196 uc = URLMimeTypeCheck(('image/jpeg', 'image/gif', 'image/png')) 197 try: 198 uc(value, message_dict) 199 except URLMimeTypeCheck.InvalidContentType: 200 raise ValidationError, _("The URL %s does not point to a valid image.") % value 201 202 203 def validate_float(value, message_dict={}): 204 data = smart_str(value) 205 try: 206 float(data) 207 except ValueError: 208 raise ValidationError, _("Please enter a valid floating point number.") -
django/db/models/__init__.py
diff --git a/django/db/models/__init__.py b/django/db/models/__init__.py index 18c47e8..97e582c 100644
a b 1 1 from django.conf import settings 2 2 from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured 3 from django.core import validators4 3 from django.db import connection 5 4 from django.db.models.loading import get_apps, get_app, get_models, get_model, register_models 6 5 from django.db.models.query import Q -
django/db/models/base.py
diff --git a/django/db/models/base.py b/django/db/models/base.py index 53307dc..b126f37 100644
a b except NameError: 11 11 import django.db.models.manipulators # Imported to register signal handler. 12 12 import django.db.models.manager # Ditto. 13 13 from django.core import validators 14 from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned, FieldError15 14 from django.db.models.fields import AutoField, ImageField 15 from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned, FieldError, ValidationError, NON_FIELD_ERRORS 16 16 from django.db.models.fields.related import OneToOneRel, ManyToOneRel, OneToOneField 17 17 from django.db.models.query import delete_objects, Q, CollectedObjects 18 18 from django.db.models.options import Options … … from django.db.models import signals 21 21 from django.db.models.loading import register_models, get_model 22 22 from django.dispatch import dispatcher 23 23 from django.utils.functional import curry 24 from django.utils.translation import ugettext_lazy as _ 24 25 from django.utils.encoding import smart_str, force_unicode, smart_unicode 25 26 from django.core.files.move import file_move_safe 26 27 from django.core.files import locks … … class Model(object): 354 355 355 356 save_base.alters_data = True 356 357 357 def validate(self): 358 def clean(self, new_data=None): 359 self.to_python() 360 self.validate(new_data) 361 362 def to_python(self): 363 error_dict = {} 364 for f in self._meta.fields: 365 try: 366 value = f.to_python(getattr(self, f.attname, f.get_default())) 367 setattr(self, f.attname, value) 368 except ValidationError, e: 369 error_dict[f.name] = e.messages 370 if error_dict: 371 raise ValidationError(error_dict) 372 373 def validate(self, new_data=None): 358 374 """ 359 First coerces all fields on this instance to their proper Python types. 360 Then runs validation on every field. Returns a dictionary of 361 field_name -> error_list. 375 Validate the data on the model, if new_data is supplied, try and use those instead of 376 actual values on the fields. Note that the fields are validated separately. 362 377 """ 378 if new_data is not None: 379 def get_value(f): 380 if f.name in new_data: 381 return f.to_python(new_data[f.name]) 382 return getattr(self, f.attname, f.get_default()) 383 else: 384 get_value = lambda f: getattr(self, f.attname, f.get_default()) 363 385 error_dict = {} 364 invalid_python = {}365 386 for f in self._meta.fields: 366 387 try: 367 setattr(self, f.attname, f.to_python(getattr(self, f.attname, f.get_default()))) 368 except validators.ValidationError, e: 388 value = get_value(f) 389 f.validate(value, instance=self) 390 if hasattr(self, 'validate_%s' % f.name): 391 getattr(self, 'validate_%s' % f.name)(value) 392 except ValidationError, e: 369 393 error_dict[f.name] = e.messages 370 invalid_python[f.name] = 1 371 for f in self._meta.fields: 372 if f.name in invalid_python: 373 continue 374 errors = f.validate_full(getattr(self, f.attname, f.get_default()), self.__dict__) 375 if errors: 376 error_dict[f.name] = errors 377 return error_dict 394 395 for un_together in self._meta.unique_together: 396 lookup = {} 397 for name in un_together: 398 if name in error_dict: 399 break 400 f = self._meta.get_field(name) 401 lookup['%s__exact' % name] = get_value(f) 402 try: 403 qset = self.__class__._default_manager.all() 404 if self.pk: 405 qset = qset.exclude(pk=self.pk) 406 obj = qset.get(**lookup) 407 error_dict[NON_FIELD_ERRORS] = _('Fields %s must be unique.') % ', '.join(un_together) 408 except self.DoesNotExist: 409 pass 410 411 if error_dict: 412 raise ValidationError(error_dict) 378 413 379 414 def _collect_sub_objects(self, seen_objs, parent=None, nullable=False): 380 415 """ -
django/db/models/fields/__init__.py
diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index 439633c..6abd261 100644
a b from django.db.models import signals 12 12 from django.db.models.query_utils import QueryWrapper 13 13 from django.dispatch import dispatcher 14 14 from django.conf import settings 15 from django.oldforms import validators as oldvalidators 15 16 from django.core import validators 16 17 from django import oldforms 17 18 from django import forms … … class Field(object): 76 77 creation_counter = 0 77 78 auto_creation_counter = -1 78 79 80 validators = [] 81 79 82 def __init__(self, verbose_name=None, name=None, primary_key=False, 80 83 max_length=None, unique=False, blank=False, null=False, 81 84 db_index=False, core=False, rel=None, default=NOT_PROVIDED, 82 85 editable=True, serialize=True, unique_for_date=None, 83 86 unique_for_month=None, unique_for_year=None, validator_list=None, 84 87 choices=None, help_text='', db_column=None, db_tablespace=None, 85 auto_created=False ):88 auto_created=False, validators=[]): 86 89 self.name = name 87 90 self.verbose_name = verbose_name 88 91 self.primary_key = primary_key … … class Field(object): 95 98 self.core, self.rel, self.default = core, rel, default 96 99 self.editable = editable 97 100 self.serialize = serialize 101 self.validators = validators + self.validators 98 102 self.validator_list = validator_list or [] 99 103 self.unique_for_date, self.unique_for_month = unique_for_date, unique_for_month 100 104 self.unique_for_year = unique_for_year … … class Field(object): 160 164 return get_creation_module().DATA_TYPES[self.get_internal_type()] % data 161 165 except KeyError: 162 166 return None 163 164 167 def unique(self): 165 168 return self._unique or self.primary_key 166 169 unique = property(unique) 167 170 168 def validate _full(self, field_data, all_data):171 def validate(self, value, instance=None): 169 172 """ 170 Returns a list of errors for this field. This is the main interface, 171 as it encapsulates some basic validation logic used by all fields. 172 Subclasses should implement validate(), not validate_full(). 173 """ 174 if not self.blank and not field_data: 175 return [_('This field is required.')] 176 try: 177 self.validate(field_data, all_data) 178 except validators.ValidationError, e: 179 return e.messages 180 return [] 181 182 def validate(self, field_data, all_data): 183 """ 184 Raises validators.ValidationError if field_data has any errors. 173 Raises validators.ValidationError if value has any errors. 185 174 Subclasses should override this to specify field-specific validation 186 logic. This method should assume field_datahas already been converted175 logic. This method should assume value has already been converted 187 176 into the appropriate data type by Field.to_python(). 188 177 """ 189 pass 178 if not self.blank and self.editable and not value: 179 raise validators.ValidationError(_('This field is required.')) 180 elist = [] 181 for validator in self.validators: 182 validator(value) 183 if self.unique and instance: 184 try: 185 qset = instance.__class__._default_manager.all() 186 if instance.pk: 187 qset = qset.exclude(pk=instance.pk) 188 obj = qset.get(**{'%s__exact' % self.name : value}) 189 raise validators.ValidationError(_('This field must be unique')) 190 except instance.DoesNotExist: 191 pass 190 192 191 193 def set_attributes_from_name(self, name): 192 194 self.name = name … … class Field(object): 340 342 core_field_names.extend(f.get_manipulator_field_names(name_prefix)) 341 343 # Now, if there are any, add the validator to this FormField. 342 344 if core_field_names: 343 params['validator_list'].append( validators.RequiredIfOtherFieldsGiven(core_field_names, ugettext_lazy("This field is required.")))345 params['validator_list'].append(oldvalidators.RequiredIfOtherFieldsGiven(core_field_names, ugettext_lazy("This field is required."))) 344 346 345 347 # Finally, add the field_names. 346 348 field_names = self.get_manipulator_field_names(name_prefix) … … class DateField(Field): 545 547 return value.date() 546 548 if isinstance(value, datetime.date): 547 549 return value 548 validators.isValidANSIDate(value, None)549 550 try: 550 551 return datetime.date(*time.strptime(value, '%Y-%m-%d')[:3]) 551 552 except ValueError: … … class DecimalField(Field): 746 747 return super(DecimalField, self).formfield(**defaults) 747 748 748 749 class EmailField(CharField): 750 validators = [validators.validate_email] 749 751 def __init__(self, *args, **kwargs): 750 752 kwargs['max_length'] = kwargs.get('max_length', 75) 751 753 CharField.__init__(self, *args, **kwargs) … … class EmailField(CharField): 753 755 def get_manipulator_field_objs(self): 754 756 return [oldforms.EmailField] 755 757 756 def validate(self, field_data, all_data):757 validators.isValidEmail(field_data, all_data)758 759 758 def formfield(self, **kwargs): 760 759 defaults = {'form_class': forms.EmailField} 761 760 defaults.update(kwargs) … … class FileField(Field): 792 791 self.always_test = True 793 792 def __call__(self, field_data, all_data): 794 793 if not all_data.get(self.other_file_field_name, False): 795 c = validators.RequiredIfOtherFieldsGiven(self.other_field_names, ugettext_lazy("This field is required."))794 c = oldvalidators.RequiredIfOtherFieldsGiven(self.other_field_names, ugettext_lazy("This field is required.")) 796 795 c(field_data, all_data) 797 796 # First, get the core fields, if any. 798 797 core_field_names = [] … … class FileField(Field): 803 802 if core_field_names: 804 803 field_list[0].validator_list.append(RequiredFileField(core_field_names, field_list[1].field_name)) 805 804 else: 806 v = validators.RequiredIfOtherFieldNotGiven(field_list[1].field_name, ugettext_lazy("This field is required."))805 v = oldvalidators.RequiredIfOtherFieldNotGiven(field_list[1].field_name, ugettext_lazy("This field is required.")) 807 806 v.always_test = True 808 807 field_list[0].validator_list.append(v) 809 808 field_list[0].is_required = field_list[1].is_required = False … … class IntegerField(Field): 971 970 972 971 class IPAddressField(Field): 973 972 empty_strings_allowed = False 973 validators = [validators.validate_ip_address4] 974 974 975 def __init__(self, *args, **kwargs): 975 976 kwargs['max_length'] = 15 976 977 Field.__init__(self, *args, **kwargs) … … class IPAddressField(Field): 981 982 def get_internal_type(self): 982 983 return "IPAddressField" 983 984 984 def validate(self, field_data, all_data):985 validators.isValidIPAddress4(field_data, None)986 987 985 def formfield(self, **kwargs): 988 986 defaults = {'form_class': forms.IPAddressField} 989 987 defaults.update(kwargs) … … class NullBooleanField(Field): 1018 1016 return super(NullBooleanField, self).formfield(**defaults) 1019 1017 1020 1018 class PhoneNumberField(IntegerField): 1019 validators = [validators.validate_phone_number] 1020 1021 1021 def get_manipulator_field_objs(self): 1022 1022 return [oldforms.PhoneNumberField] 1023 1023 1024 1024 def get_internal_type(self): 1025 1025 return "PhoneNumberField" 1026 1026 1027 def validate(self, field_data, all_data):1028 validators.isValidPhone(field_data, all_data)1029 1030 1027 def formfield(self, **kwargs): 1031 1028 from django.contrib.localflavor.us.forms import USPhoneNumberField 1032 1029 defaults = {'form_class': USPhoneNumberField} … … class PositiveSmallIntegerField(IntegerField): 1058 1055 return super(PositiveSmallIntegerField, self).formfield(**defaults) 1059 1056 1060 1057 class SlugField(CharField): 1058 validators = [validators.validate_slug] 1061 1059 def __init__(self, *args, **kwargs): 1062 1060 kwargs['max_length'] = kwargs.get('max_length', 50) 1063 kwargs.setdefault('validator_list', []).append(validators.isSlug)1064 1061 # Set db_index=True unless it's been set manually. 1065 1062 if 'db_index' not in kwargs: 1066 1063 kwargs['db_index'] = True … … class URLField(CharField): 1156 1153 def __init__(self, verbose_name=None, name=None, verify_exists=True, **kwargs): 1157 1154 kwargs['max_length'] = kwargs.get('max_length', 200) 1158 1155 if verify_exists: 1159 kwargs.setdefault('validator _list', []).append(validators.isExistingURL)1156 kwargs.setdefault('validators', []).append(validators.validate_existing_url) 1160 1157 self.verify_exists = verify_exists 1161 1158 CharField.__init__(self, verbose_name, name, **kwargs) 1162 1159 -
django/db/models/fields/related.py
diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py index ca25df2..061ea08 100644
a b class ManyToManyField(RelatedField, Field): 770 770 objects = mod._default_manager.in_bulk(pks) 771 771 if len(objects) != len(pks): 772 772 badkeys = [k for k in pks if k not in objects] 773 raise validator s.ValidationError, ungettext("Please enter valid %(self)s IDs. The value %(value)r is invalid.",773 raise validator_list.ValidationError, ungettext("Please enter valid %(self)s IDs. The value %(value)r is invalid.", 774 774 "Please enter valid %(self)s IDs. The values %(value)r are invalid.", len(badkeys)) % { 775 775 'self': self.verbose_name, 776 776 'value': len(badkeys) == 1 and badkeys[0] or tuple(badkeys), -
django/forms/__init__.py
diff --git a/django/forms/__init__.py b/django/forms/__init__.py index 0d9c68f..8321417 100644
a b TODO: 10 10 "This form field requires foo.js" and form.js_includes() 11 11 """ 12 12 13 from util import ValidationError13 from django.core.exceptions import ValidationError, NON_FIELD_ERRORS 14 14 from widgets import * 15 15 from fields import * 16 16 from forms import * 17 17 from models import * 18 from formsets import * -
django/forms/fields.py
diff --git a/django/forms/fields.py b/django/forms/fields.py index 6b834af..290fcbf 100644
a b except NameError: 25 25 26 26 from django.utils.translation import ugettext_lazy as _ 27 27 from django.utils.encoding import smart_unicode, smart_str 28 from django.core.exceptions import ValidationError 29 from django.core import validators 28 30 29 from util import ErrorList, ValidationError30 31 from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, FileInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple, DateTimeInput 32 from util import ErrorList 31 33 from django.core.files.uploadedfile import SimpleUploadedFile as UploadedFile 32 34 33 35 __all__ = ( … … EMPTY_VALUES = (None, '') 47 49 48 50 class Field(object): 49 51 widget = TextInput # Default widget to use when rendering this type of Field. 52 validators = [] 50 53 hidden_widget = HiddenInput # Default widget to use when rendering this as "hidden". 51 54 default_error_messages = { 52 55 'required': _(u'This field is required.'), … … class Field(object): 57 60 creation_counter = 0 58 61 59 62 def __init__(self, required=True, widget=None, label=None, initial=None, 60 help_text=None, error_messages=None ):63 help_text=None, error_messages=None, validators=[]): 61 64 # required -- Boolean that specifies whether the field is required. 62 65 # True by default. 63 66 # widget -- A Widget class, or instance of a Widget class, that should … … class Field(object): 71 74 # initial -- A value to use in this Field's initial display. This value 72 75 # is *not* used as a fallback if data isn't given. 73 76 # help_text -- An optional string to use as "help text" for this Field. 77 # validators -- Optional list of additional validator functions 74 78 if label is not None: 75 79 label = smart_unicode(label) 80 self.validators = self.validators + validators 76 81 self.required, self.label, self.initial = required, label, initial 77 82 self.help_text = smart_unicode(help_text or '') 78 83 widget = widget or self.widget … … class Field(object): 100 105 messages.update(error_messages or {}) 101 106 self.error_messages = messages 102 107 108 def to_python(self, value): 109 if value in EMPTY_VALUES: 110 return None 111 return smart_unicode(value) 112 113 def validate(self, value): 114 if self.required and value in EMPTY_VALUES: 115 raise ValidationError(self.error_messages['required']) 116 elif value in EMPTY_VALUES: 117 return 118 elist = ErrorList() 119 for validator in self.validators: 120 try: 121 validator(value, self.error_messages) 122 except ValidationError, e: 123 elist.extend(e.messages) 124 if elist: 125 raise ValidationError(elist) 126 103 127 def clean(self, value): 104 128 """ 105 129 Validates the given value and returns its "cleaned" value as an … … class Field(object): 107 131 108 132 Raises ValidationError for any errors. 109 133 """ 110 if self.required and value in EMPTY_VALUES:111 raise ValidationError(self.error_messages['required'])134 value = self.to_python(value) 135 self.validate(value) 112 136 return value 113 137 114 138 def widget_attrs(self, widget): … … class CharField(Field): 135 159 self.max_length, self.min_length = max_length, min_length 136 160 super(CharField, self).__init__(*args, **kwargs) 137 161 138 def clean(self, value): 139 "Validates max_length and min_length. Returns a Unicode object." 140 super(CharField, self).clean(value) 162 def to_python(self, value): 141 163 if value in EMPTY_VALUES: 142 164 return u'' 143 value = smart_unicode(value) 165 return smart_unicode(value) 166 167 def validate(self, value): 168 "Validates max_length and min_length. Returns a Unicode object." 169 super(CharField, self).validate(value) 144 170 value_length = len(value) 171 if value_length == 0 and not self.required: 172 return 145 173 if self.max_length is not None and value_length > self.max_length: 146 174 raise ValidationError(self.error_messages['max_length'] % {'max': self.max_length, 'length': value_length}) 147 175 if self.min_length is not None and value_length < self.min_length: 148 176 raise ValidationError(self.error_messages['min_length'] % {'min': self.min_length, 'length': value_length}) 149 return value150 177 151 178 def widget_attrs(self, widget): 152 179 if self.max_length is not None and isinstance(widget, (TextInput, PasswordInput)): … … class IntegerField(Field): 164 191 self.max_value, self.min_value = max_value, min_value 165 192 super(IntegerField, self).__init__(*args, **kwargs) 166 193 167 def clean(self, value): 168 """ 169 Validates that int() can be called on the input. Returns the result 170 of int(). Returns None for empty values. 171 """ 172 super(IntegerField, self).clean(value) 194 def to_python(self, value): 173 195 if value in EMPTY_VALUES: 174 196 return None 175 197 try: 176 value = int(str(value))198 return int(smart_str(value)) 177 199 except (ValueError, TypeError): 178 200 raise ValidationError(self.error_messages['invalid']) 201 202 def validate(self, value): 203 """ 204 Validates that int() can be called on the input. Returns the result 205 of int(). Returns None for empty values. 206 """ 207 super(IntegerField, self).validate(value) 208 if value is None: return 179 209 if self.max_value is not None and value > self.max_value: 180 210 raise ValidationError(self.error_messages['max_value'] % self.max_value) 181 211 if self.min_value is not None and value < self.min_value: 182 212 raise ValidationError(self.error_messages['min_value'] % self.min_value) 183 return value184 213 185 214 class FloatField(Field): 186 215 default_error_messages = { … … class FloatField(Field): 193 222 self.max_value, self.min_value = max_value, min_value 194 223 Field.__init__(self, *args, **kwargs) 195 224 196 def clean(self, value):225 def to_python(self, value): 197 226 """ 198 227 Validates that float() can be called on the input. Returns a float. 199 228 Returns None for empty values. 200 229 """ 201 super(FloatField, self).clean(value) 202 if not self.required and value in EMPTY_VALUES: 230 if value in EMPTY_VALUES: 203 231 return None 204 232 try: 205 value =float(value)233 return float(value) 206 234 except (ValueError, TypeError): 207 235 raise ValidationError(self.error_messages['invalid']) 236 237 def validate(self, value): 238 super(FloatField, self).validate(value) 239 if value is None: return 208 240 if self.max_value is not None and value > self.max_value: 209 241 raise ValidationError(self.error_messages['max_value'] % self.max_value) 210 242 if self.min_value is not None and value < self.min_value: 211 243 raise ValidationError(self.error_messages['min_value'] % self.min_value) 212 return value213 244 214 245 class DecimalField(Field): 215 246 default_error_messages = { … … class DecimalField(Field): 226 257 self.max_digits, self.decimal_places = max_digits, decimal_places 227 258 Field.__init__(self, *args, **kwargs) 228 259 229 def clean(self, value):260 def to_python(self, value): 230 261 """ 231 262 Validates that the input is a decimal number. Returns a Decimal 232 263 instance. Returns None for empty values. Ensures that there are no more 233 264 than max_digits in the number, and no more than decimal_places digits 234 265 after the decimal point. 235 266 """ 236 super(DecimalField, self).clean(value) 237 if not self.required and value in EMPTY_VALUES: 267 if value in EMPTY_VALUES: 238 268 return None 239 269 value = smart_str(value).strip() 240 270 try: 241 value =Decimal(value)271 return Decimal(value) 242 272 except DecimalException: 243 273 raise ValidationError(self.error_messages['invalid']) 274 275 def validate(self, value): 276 super(DecimalField, self).validate(value) 277 if value is None: return 244 278 pieces = str(value).lstrip("-").split('.') 245 279 decimals = (len(pieces) == 2) and len(pieces[1]) or 0 246 280 digits = len(pieces[0]) … … class DecimalField(Field): 254 288 raise ValidationError(self.error_messages['max_decimal_places'] % self.decimal_places) 255 289 if self.max_digits is not None and self.decimal_places is not None and digits > (self.max_digits - self.decimal_places): 256 290 raise ValidationError(self.error_messages['max_whole_digits'] % (self.max_digits - self.decimal_places)) 257 return value258 291 259 292 DEFAULT_DATE_INPUT_FORMATS = ( 260 293 '%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', # '2006-10-25', '10/25/2006', '10/25/06' … … class DateField(Field): 273 306 super(DateField, self).__init__(*args, **kwargs) 274 307 self.input_formats = input_formats or DEFAULT_DATE_INPUT_FORMATS 275 308 276 def clean(self, value):309 def to_python(self, value): 277 310 """ 278 311 Validates that the input can be converted to a date. Returns a Python 279 312 datetime.date object. 280 313 """ 281 super(DateField, self).clean(value)282 314 if value in EMPTY_VALUES: 283 315 return None 284 316 if isinstance(value, datetime.datetime): … … class TimeField(Field): 306 338 super(TimeField, self).__init__(*args, **kwargs) 307 339 self.input_formats = input_formats or DEFAULT_TIME_INPUT_FORMATS 308 340 309 def clean(self, value):341 def to_python(self, value): 310 342 """ 311 343 Validates that the input can be converted to a time. Returns a Python 312 344 datetime.time object. 313 345 """ 314 super(TimeField, self).clean(value)315 346 if value in EMPTY_VALUES: 316 347 return None 317 348 if isinstance(value, datetime.time): … … class DateTimeField(Field): 345 376 super(DateTimeField, self).__init__(*args, **kwargs) 346 377 self.input_formats = input_formats or DEFAULT_DATETIME_INPUT_FORMATS 347 378 348 def clean(self, value):379 def to_python(self, value): 349 380 """ 350 381 Validates that the input can be converted to a datetime. Returns a 351 382 Python datetime.datetime object. 352 383 """ 353 super(DateTimeField, self).clean(value)354 384 if value in EMPTY_VALUES: 355 385 return None 356 386 if isinstance(value, datetime.datetime): … … class RegexField(CharField): 387 417 regex = re.compile(regex) 388 418 self.regex = regex 389 419 390 def clean(self, value):420 def validate(self, value): 391 421 """ 392 422 Validates that the input matches the regular expression. Returns a 393 423 Unicode object. 394 424 """ 395 value = super(RegexField, self).clean(value)425 super(RegexField, self).validate(value) 396 426 if value == u'': 397 return value427 return 398 428 if not self.regex.search(value): 399 429 raise ValidationError(self.error_messages['invalid']) 400 return value401 430 402 431 email_re = re.compile( 403 432 r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*" # dot-atom 404 433 r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"' # quoted-string 405 434 r')@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$', re.IGNORECASE) # domain 406 435 407 class EmailField( RegexField):436 class EmailField(CharField): 408 437 default_error_messages = { 409 438 'invalid': _(u'Enter a valid e-mail address.'), 410 439 } 411 412 def __init__(self, max_length=None, min_length=None, *args, **kwargs): 413 RegexField.__init__(self, email_re, max_length, min_length, *args, 414 **kwargs) 440 validators = [validators.validate_email] 415 441 416 442 try: 417 443 from django.conf import settings … … class FileField(Field): 425 451 widget = FileInput 426 452 default_error_messages = { 427 453 'invalid': _(u"No file was submitted. Check the encoding type on the form."), 428 'missing': _(u"No file was submitted."),429 454 'empty': _(u"The submitted file is empty."), 430 455 } 431 456 432 def __init__(self, *args, **kwargs): 433 super(FileField, self).__init__(*args, **kwargs) 434 435 def clean(self, data, initial=None): 436 super(FileField, self).clean(initial or data) 457 def to_python(self, data, initial=None): 437 458 if not self.required and data in EMPTY_VALUES: 438 459 return None 439 460 elif not data and initial: … … class FileField(Field): 447 468 category = DeprecationWarning, 448 469 stacklevel = 2 449 470 ) 471 if not data: 472 raise ValidationError(self.error_messages['invalid']) 450 473 data = UploadedFile(data['filename'], data['content']) 451 474 452 475 try: … … class FileField(Field): 459 482 raise ValidationError(self.error_messages['invalid']) 460 483 if not file_size: 461 484 raise ValidationError(self.error_messages['empty']) 462 463 485 return data 464 486 487 def clean(self, value, initial=None): 488 "overriden clean to provide extra argument initial" 489 value = self.to_python(value, initial) 490 self.validate(value) 491 return value 492 465 493 class ImageField(FileField): 466 494 default_error_messages = { 467 495 'invalid_image': _(u"Upload a valid image. The file you uploaded was either not an image or a corrupted image."), 468 496 } 469 497 470 def clean(self, data, initial=None): 471 """ 472 Checks that the file-upload field data contains a valid image (GIF, JPG, 473 PNG, possibly others -- whatever the Python Imaging Library supports). 474 """ 475 f = super(ImageField, self).clean(data, initial) 476 if f is None: 477 return None 478 elif not data and initial: 479 return initial 498 def validate(self, data): 499 super(ImageField, self).validate(data) 500 if data is None: 501 return 480 502 from PIL import Image 481 482 503 # We need to get a file object for PIL. We might have a path or we might 483 504 # have to read the data into memory. 484 505 if hasattr(data, 'temporary_file_path'): … … class ImageField(FileField): 486 507 else: 487 508 if hasattr(data, 'read'): 488 509 file = StringIO(data.read()) 510 elif isinstance(data, UploadedFile): 511 file = StringIO(data.data.read()) 512 elif hasattr(data, 'seek') and callable(data.seek): 513 data.seek(0) 514 file = data 489 515 else: 490 file = StringIO(data['content'])516 file = data 491 517 492 518 try: 493 519 # load() is the only method that can spot a truncated JPEG, … … class ImageField(FileField): 511 537 raise 512 538 except Exception: # Python Imaging Library doesn't recognize it as an image 513 539 raise ValidationError(self.error_messages['invalid_image']) 514 if hasattr(f, 'seek') and callable(f.seek):515 f.seek(0)516 return f517 540 518 541 url_re = re.compile( 519 542 r'^https?://' # http:// or https:// … … class URLField(RegexField): 536 559 self.verify_exists = verify_exists 537 560 self.user_agent = validator_user_agent 538 561 539 def clean(self, value): 562 def to_python(self, value): 563 value = super(URLField, self).to_python(value) 540 564 # If no URL scheme given, assume http:// 541 565 if value and '://' not in value: 542 566 value = u'http://%s' % value 543 567 # If no URL path given, assume / 544 if value and not urlparse.urlsplit(value) .path:568 if value and not urlparse.urlsplit(value)[2]: 545 569 value += '/' 546 value = super(URLField, self).clean(value) 570 return value 571 572 def validate(self, value): 573 super(URLField, self).validate(value) 547 574 if value == u'': 548 return value575 return 549 576 if self.verify_exists: 550 import urllib2 551 headers = { 552 "Accept": "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5", 553 "Accept-Language": "en-us,en;q=0.5", 554 "Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", 555 "Connection": "close", 556 "User-Agent": self.user_agent, 557 } 558 try: 559 req = urllib2.Request(value, None, headers) 560 u = urllib2.urlopen(req) 561 except ValueError: 562 raise ValidationError(self.error_messages['invalid']) 563 except: # urllib2.URLError, httplib.InvalidURL, etc. 564 raise ValidationError(self.error_messages['invalid_link']) 565 return value 577 # we cannot put this in self.validators because its conditional 578 validators.validate_existing_url(value, self.error_messages) 566 579 567 580 class BooleanField(Field): 568 581 widget = CheckboxInput 569 582 570 def clean(self, value):583 def to_python(self, value): 571 584 """Returns a Python boolean object.""" 572 585 # Explicitly check for the string 'False', which is what a hidden field 573 586 # will submit for False. Because bool("True") == True, we don't need to … … class BooleanField(Field): 576 589 value = False 577 590 else: 578 591 value = bool(value) 579 super(BooleanField, self).clean(value)580 if not value and self.required:581 raise ValidationError(self.error_messages['required'])582 592 return value 583 593 594 def validate(self, value): 595 if self.required and not value: 596 raise ValidationError(self.error_messages['required']) 597 598 584 599 class NullBooleanField(BooleanField): 585 600 """ 586 601 A field whose valid values are None, True and False. Invalid values are 587 602 cleaned to None. 603 604 Note that validation doesn't apply here. 588 605 """ 589 606 widget = NullBooleanSelect 590 607 591 def clean(self, value):608 def to_python(self, value): 592 609 return {True: True, False: False}.get(value, None) 593 610 611 def validate(self, value): 612 pass 613 614 594 615 class ChoiceField(Field): 595 616 widget = Select 596 617 default_error_messages = { … … class ChoiceField(Field): 614 635 615 636 choices = property(_get_choices, _set_choices) 616 637 617 def clean(self, value): 618 """ 619 Validates that the input is in self.choices. 620 """ 621 value = super(ChoiceField, self).clean(value) 622 if value in EMPTY_VALUES: 623 value = u'' 624 value = smart_unicode(value) 625 if value == u'': 626 return value 638 def validate(self, value): 639 super(ChoiceField, self).validate(value) 640 if value is None and not self.required: 641 return 627 642 if not self.valid_value(value): 628 643 raise ValidationError(self.error_messages['invalid_choice'] % {'value': value}) 629 return value630 644 631 645 def valid_value(self, value): 632 646 "Check to see if the provided value is a valid choice" … … class MultipleChoiceField(ChoiceField): 649 663 'invalid_list': _(u'Enter a list of values.'), 650 664 } 651 665 652 def clean(self, value):666 def to_python(self, value): 653 667 """ 654 668 Validates that the input is a list or tuple. 655 669 """ 656 if self.required and not value: 657 raise ValidationError(self.error_messages['required']) 658 elif not self.required and not value: 670 if not value: 659 671 return [] 660 672 if not isinstance(value, (list, tuple)): 661 673 raise ValidationError(self.error_messages['invalid_list']) 662 new_value = [smart_unicode(val) for val in value] 674 return [smart_unicode(val) for val in value] 675 676 def validate(self, value): 663 677 # Validate that each value in the value list is in self.choices. 664 for val in new_value: 678 if self.required and value == []: 679 raise ValidationError(self.error_messages['required']) 680 for val in value: 665 681 if not self.valid_value(val): 666 682 raise ValidationError(self.error_messages['invalid_choice'] % {'value': val}) 667 return new_value668 683 669 684 class ComboField(Field): 670 685 """ … … class ComboField(Field): 679 694 f.required = False 680 695 self.fields = fields 681 696 682 def clean(self, value): 697 def to_python(self, value): 698 for field in self.fields: 699 value = field.to_python(value) 700 return value 701 702 def validate(self, value): 683 703 """ 684 704 Validates the given value against all of self.fields, which is a 685 705 list of Field instances. 686 706 """ 687 super(ComboField, self). clean(value)707 super(ComboField, self).validate(value) 688 708 for field in self.fields: 689 value = field.clean(value) 690 return value 709 field.validate(value) 691 710 692 711 class MultiValueField(Field): 693 712 """ … … class MultiValueField(Field): 719 738 f.required = False 720 739 self.fields = fields 721 740 722 def clean(self, value):741 def to_python(self, value): 723 742 """ 724 743 Validates every value in the given list. A value is validated against 725 744 the corresponding Field in self.fields. … … class MultiValueField(Field): 733 752 if not value or isinstance(value, (list, tuple)): 734 753 if not value or not [v for v in value if v not in EMPTY_VALUES]: 735 754 if self.required: 736 r aise ValidationError(self.error_messages['required'])755 return None 737 756 else: 738 757 return self.compress([]) 739 758 else: 740 759 raise ValidationError(self.error_messages['invalid']) 760 741 761 for i, field in enumerate(self.fields): 742 762 try: 743 763 field_value = value[i] … … class SplitDateTimeField(MultiValueField): 821 841 return datetime.datetime.combine(*data_list) 822 842 return None 823 843 824 ipv4_re = re.compile(r'^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$') 825 826 class IPAddressField(RegexField): 844 class IPAddressField(CharField): 827 845 default_error_messages = { 828 846 'invalid': _(u'Enter a valid IPv4 address.'), 829 847 } 830 831 def __init__(self, *args, **kwargs): 832 super(IPAddressField, self).__init__(ipv4_re, *args, **kwargs) 848 validators = [validators.validate_ip_address4] -
django/forms/forms.py
diff --git a/django/forms/forms.py b/django/forms/forms.py index 753ee25..05936f2 100644
a b from django.utils.datastructures import SortedDict 8 8 from django.utils.html import escape 9 9 from django.utils.encoding import StrAndUnicode, smart_unicode, force_unicode 10 10 from django.utils.safestring import mark_safe 11 from django.forms import ValidationError, NON_FIELD_ERRORS 11 12 12 13 from fields import Field, FileField 13 14 from widgets import Media, media_property, TextInput, Textarea 14 from util import flatatt, ErrorDict, ErrorList , ValidationError15 from util import flatatt, ErrorDict, ErrorList 15 16 16 17 __all__ = ('BaseForm', 'Form') 17 18 18 NON_FIELD_ERRORS = '__all__'19 19 20 20 def pretty_name(name): 21 21 "Converts 'first_name' to 'First name'" … … class BaseForm(StrAndUnicode): 217 217 else: 218 218 value = field.clean(value) 219 219 self.cleaned_data[name] = value 220 # FIXME deprecated - keeping this here for backwards compatibility 220 221 if hasattr(self, 'clean_%s' % name): 221 222 value = getattr(self, 'clean_%s' % name)() 222 223 self.cleaned_data[name] = value 224 225 if hasattr(self, 'validate_%s' % name): 226 getattr(self, 'validate_%s' % name)(value) 223 227 except ValidationError, e: 224 self._errors[name] = e.messages228 self._errors[name] = ErrorList(e.messages) 225 229 if name in self.cleaned_data: 226 230 del self.cleaned_data[name] 227 231 try: 228 self. cleaned_data = self.clean()232 self.validate() 229 233 except ValidationError, e: 230 self._errors[NON_FIELD_ERRORS] = e.messages 234 if hasattr(e, 'message_dict'): 235 for k, v in e.message_dict.items(): 236 self._errors.setdefault(k, []).extend(v) 237 else: 238 self._errors[NON_FIELD_ERRORS] = ErrorList(e.messages) 231 239 if self._errors: 232 240 delattr(self, 'cleaned_data') 233 241 234 242 def clean(self): 235 243 """ 244 FIXME: deprecated, use validate() instead 245 236 246 Hook for doing any extra form-wide cleaning after Field.clean() been 237 247 called on every field. Any ValidationError raised by this method will 238 248 not be associated with a particular field; it will have a special-case … … class BaseForm(StrAndUnicode): 274 284 return media 275 285 media = property(_get_media) 276 286 287 def validate(self): 288 self.cleaned_data = self.clean() 289 277 290 def is_multipart(self): 278 291 """ 279 292 Returns True if the form needs to be multipart-encrypted, i.e. it has -
django/forms/formsets.py
diff --git a/django/forms/formsets.py b/django/forms/formsets.py index 2f13bf5..a0a9199 100644
a b from django.utils.encoding import StrAndUnicode 3 3 from django.utils.safestring import mark_safe 4 4 from fields import IntegerField, BooleanField 5 5 from widgets import Media, HiddenInput 6 from util import ErrorList, ValidationError 6 from django.core.exceptions import ValidationError 7 from util import ErrorList 7 8 8 9 __all__ = ('BaseFormSet', 'all_valid') 9 10 -
django/forms/models.py
diff --git a/django/forms/models.py b/django/forms/models.py index 56e19e7..c89f110 100644
a b from warnings import warn 8 8 from django.utils.translation import ugettext_lazy as _ 9 9 from django.utils.encoding import smart_unicode 10 10 from django.utils.datastructures import SortedDict 11 from django.core.exceptions import ImproperlyConfigured, ValidationError 12 from django.forms.util import ErrorList 11 13 12 from util import ValidationError, ErrorList13 14 from forms import BaseForm, get_declared_fields 14 15 from fields import Field, ChoiceField, IntegerField, EMPTY_VALUES 15 16 from widgets import Select, SelectMultiple, HiddenInput, MultipleHiddenInput … … class BaseModelForm(BaseForm): 262 263 BaseForm.__init__(self, data, files, auto_id, prefix, object_data, 263 264 error_class, label_suffix, empty_permitted) 264 265 266 def validate(self): 267 super(BaseModelForm, self).validate() 268 if self._errors: 269 return 270 self.instance.clean(self.cleaned_data) 271 265 272 def save(self, commit=True): 266 273 """ 267 274 Saves this ``form``'s cleaned_data into model instance … … class ModelChoiceField(ChoiceField): 564 571 565 572 choices = property(_get_choices, ChoiceField._set_choices) 566 573 567 def clean(self, value): 568 Field.clean(self, value) 569 if value in EMPTY_VALUES: 574 def to_python(self, value): 575 if self.required and value in EMPTY_VALUES: 576 raise ValidationError(self.error_messages['required']) 577 elif value in EMPTY_VALUES: 570 578 return None 571 579 try: 572 580 value = self.queryset.get(pk=value) … … class ModelChoiceField(ChoiceField): 574 582 raise ValidationError(self.error_messages['invalid_choice']) 575 583 return value 576 584 585 def validate(self, value): 586 pass 587 577 588 class ModelMultipleChoiceField(ModelChoiceField): 578 589 """A MultipleChoiceField whose choices are a model QuerySet.""" 579 590 hidden_widget = MultipleHiddenInput … … class ModelMultipleChoiceField(ModelChoiceField): 590 601 cache_choices, required, widget, label, initial, help_text, 591 602 *args, **kwargs) 592 603 593 def clean(self, value):604 def to_python(self, value): 594 605 if self.required and not value: 595 606 raise ValidationError(self.error_messages['required']) 596 607 elif not self.required and not value: … … class ModelMultipleChoiceField(ModelChoiceField): 606 617 else: 607 618 final_values.append(obj) 608 619 return final_values 620 -
django/forms/util.py
diff --git a/django/forms/util.py b/django/forms/util.py index 3d80ad2..6355949 100644
a b class ErrorList(list, StrAndUnicode): 36 36 def __unicode__(self): 37 37 return self.as_ul() 38 38 39 def __repr__(self): 40 return repr([force_unicode(e) for e in self]) 41 39 42 def as_ul(self): 40 43 if not self: return u'' 41 44 return mark_safe(u'<ul class="errorlist">%s</ul>' … … class ErrorList(list, StrAndUnicode): 44 47 def as_text(self): 45 48 if not self: return u'' 46 49 return u'\n'.join([u'* %s' % force_unicode(e) for e in self]) 47 48 def __repr__(self):49 return repr([force_unicode(e) for e in self])50 51 class ValidationError(Exception):52 def __init__(self, message):53 """54 ValidationError can be passed any object that can be printed (usually55 a string) or a list of objects.56 """57 if isinstance(message, list):58 self.messages = ErrorList([smart_unicode(msg) for msg in message])59 else:60 message = smart_unicode(message)61 self.messages = ErrorList([message])62 63 def __str__(self):64 # This is needed because, without a __str__(), printing an exception65 # instance would result in this:66 # AttributeError: ValidationError instance has no attribute 'args'67 # See http://www.python.org/doc/current/tut/node10.html#handling68 return repr(self.messages) -
django/newforms/__init__.py
diff --git a/django/newforms/__init__.py b/django/newforms/__init__.py index 5f319f8..b437d84 100644
a b warnings.warn( 4 4 message = "django.newforms is no longer new. Import django.forms instead.", 5 5 stacklevel = 2 6 6 ) 7 from django.forms import * 8 No newline at end of file 7 from django.forms import * -
django/oldforms/__init__.py
diff --git a/django/oldforms/__init__.py b/django/oldforms/__init__.py index 2a300df..2fd510e 100644
a b 1 from django. coreimport validators1 from django.oldforms import validators 2 2 from django.core.exceptions import PermissionDenied 3 3 from django.utils.html import escape 4 4 from django.utils.safestring import mark_safe -
new file django/oldforms/validators.py
diff --git a/django/oldforms/validators.py b/django/oldforms/validators.py new file mode 100644 index 0000000..7500347
- + 1 """ 2 A library of validators that return None and raise ValidationError when the 3 provided data isn't valid. 4 5 Validators may be callable classes, and they may have an 'always_test' 6 attribute. If an 'always_test' attribute exists (regardless of value), the 7 validator will *always* be run, regardless of whether its associated 8 form field is required. 9 """ 10 11 import urllib2 12 import re 13 try: 14 from decimal import Decimal, DecimalException 15 except ImportError: 16 from django.utils._decimal import Decimal, DecimalException # Python 2.3 17 18 from django.conf import settings 19 from django.utils.translation import ugettext as _, ugettext_lazy, ungettext 20 from django.utils.functional import Promise, lazy 21 from django.utils.encoding import force_unicode, smart_str 22 from django.core.exceptions import ValidationError 23 24 _datere = r'\d{4}-\d{1,2}-\d{1,2}' 25 _timere = r'(?:[01]?[0-9]|2[0-3]):[0-5][0-9](?::[0-5][0-9])?' 26 alnum_re = re.compile(r'^\w+$') 27 alnumurl_re = re.compile(r'^[-\w/]+$') 28 ansi_date_re = re.compile('^%s$' % _datere) 29 ansi_time_re = re.compile('^%s$' % _timere) 30 ansi_datetime_re = re.compile('^%s %s$' % (_datere, _timere)) 31 email_re = re.compile( 32 r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*" # dot-atom 33 r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*"' # quoted-string 34 r')@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$', re.IGNORECASE) # domain 35 integer_re = re.compile(r'^-?\d+$') 36 ip4_re = re.compile(r'^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$') 37 phone_re = re.compile(r'^[A-PR-Y0-9]{3}-[A-PR-Y0-9]{3}-[A-PR-Y0-9]{4}$', re.IGNORECASE) 38 slug_re = re.compile(r'^[-\w]+$') 39 url_re = re.compile(r'^https?://\S+$') 40 41 lazy_inter = lazy(lambda a,b: force_unicode(a) % b, unicode) 42 43 44 class CriticalValidationError(Exception): 45 def __init__(self, message): 46 "ValidationError can be passed a string or a list." 47 if isinstance(message, list): 48 self.messages = [force_unicode(msg) for msg in message] 49 else: 50 assert isinstance(message, (basestring, Promise)), ("'%s' should be a string" % message) 51 self.messages = [force_unicode(message)] 52 53 def __str__(self): 54 return str(self.messages) 55 56 57 def isAlphaNumeric(field_data, all_data): 58 # DONE 59 if not alnum_re.search(field_data): 60 raise ValidationError, _("This value must contain only letters, numbers and underscores.") 61 62 def isAlphaNumericURL(field_data, all_data): 63 # DONE 64 if not alnumurl_re.search(field_data): 65 raise ValidationError, _("This value must contain only letters, numbers, underscores, dashes or slashes.") 66 67 def isSlug(field_data, all_data): 68 # DONE 69 if not slug_re.search(field_data): 70 raise ValidationError, _("This value must contain only letters, numbers, underscores or hyphens.") 71 72 def isLowerCase(field_data, all_data): 73 # DONE 74 if field_data.lower() != field_data: 75 raise ValidationError, _("Uppercase letters are not allowed here.") 76 77 def isUpperCase(field_data, all_data): 78 # DONE 79 if field_data.upper() != field_data: 80 raise ValidationError, _("Lowercase letters are not allowed here.") 81 82 def isCommaSeparatedIntegerList(field_data, all_data): 83 # DONE 84 for supposed_int in field_data.split(','): 85 try: 86 int(supposed_int) 87 except ValueError: 88 raise ValidationError, _("Enter only digits separated by commas.") 89 90 def isCommaSeparatedEmailList(field_data, all_data): 91 # DONE 92 """ 93 Checks that field_data is a string of e-mail addresses separated by commas. 94 Blank field_data values will not throw a validation error, and whitespace 95 is allowed around the commas. 96 """ 97 for supposed_email in field_data.split(','): 98 try: 99 isValidEmail(supposed_email.strip(), '') 100 except ValidationError: 101 raise ValidationError, _("Enter valid e-mail addresses separated by commas.") 102 103 def isValidIPAddress4(field_data, all_data): 104 # DONE 105 if not ip4_re.search(field_data): 106 raise ValidationError, _("Please enter a valid IP address.") 107 108 def isNotEmpty(field_data, all_data): 109 # DONE 110 if field_data.strip() == '': 111 raise ValidationError, _("Empty values are not allowed here.") 112 113 def isOnlyDigits(field_data, all_data): 114 # DONE 115 if not field_data.isdigit(): 116 raise ValidationError, _("Non-numeric characters aren't allowed here.") 117 118 def isNotOnlyDigits(field_data, all_data): 119 # DONE 120 if field_data.isdigit(): 121 raise ValidationError, _("This value can't be comprised solely of digits.") 122 123 def isInteger(field_data, all_data): 124 # DONE 125 # This differs from isOnlyDigits because this accepts the negative sign 126 if not integer_re.search(field_data): 127 raise ValidationError, _("Enter a whole number.") 128 129 def isOnlyLetters(field_data, all_data): 130 # DONE 131 if not field_data.isalpha(): 132 raise ValidationError, _("Only alphabetical characters are allowed here.") 133 134 def _isValidDate(date_string): 135 # DONE 136 """ 137 A helper function used by isValidANSIDate and isValidANSIDatetime to 138 check if the date is valid. The date string is assumed to already be in 139 YYYY-MM-DD format. 140 """ 141 from datetime import date 142 # Could use time.strptime here and catch errors, but datetime.date below 143 # produces much friendlier error messages. 144 year, month, day = map(int, date_string.split('-')) 145 try: 146 date(year, month, day) 147 except ValueError, e: 148 msg = _('Invalid date: %s') % _(str(e)) 149 raise ValidationError, msg 150 151 def isValidANSIDate(field_data, all_data): 152 # DONE 153 if not ansi_date_re.search(field_data): 154 raise ValidationError, _('Enter a valid date in YYYY-MM-DD format.') 155 _isValidDate(field_data) 156 157 def isValidANSITime(field_data, all_data): 158 # DONE 159 if not ansi_time_re.search(field_data): 160 raise ValidationError, _('Enter a valid time in HH:MM format.') 161 162 def isValidANSIDatetime(field_data, all_data): 163 # DONE 164 if not ansi_datetime_re.search(field_data): 165 raise ValidationError, _('Enter a valid date/time in YYYY-MM-DD HH:MM format.') 166 _isValidDate(field_data.split()[0]) 167 168 def isValidEmail(field_data, all_data): 169 # DONE 170 if not email_re.search(field_data): 171 raise ValidationError, _('Enter a valid e-mail address.') 172 173 def isValidImage(field_data, all_data): 174 """ 175 Checks that the file-upload field data contains a valid image (GIF, JPG, 176 PNG, possibly others -- whatever the Python Imaging Library supports). 177 """ 178 from PIL import Image 179 from cStringIO import StringIO 180 try: 181 content = field_data.read() 182 except TypeError: 183 raise ValidationError, _("No file was submitted. Check the encoding type on the form.") 184 try: 185 # load() is the only method that can spot a truncated JPEG, 186 # but it cannot be called sanely after verify() 187 trial_image = Image.open(StringIO(content)) 188 trial_image.load() 189 # verify() is the only method that can spot a corrupt PNG, 190 # but it must be called immediately after the constructor 191 trial_image = Image.open(StringIO(content)) 192 trial_image.verify() 193 except Exception: # Python Imaging Library doesn't recognize it as an image 194 raise ValidationError, _("Upload a valid image. The file you uploaded was either not an image or a corrupted image.") 195 196 def isValidImageURL(field_data, all_data): 197 uc = URLMimeTypeCheck(('image/jpeg', 'image/gif', 'image/png')) 198 try: 199 uc(field_data, all_data) 200 except URLMimeTypeCheck.InvalidContentType: 201 raise ValidationError, _("The URL %s does not point to a valid image.") % field_data 202 203 def isValidPhone(field_data, all_data): 204 if not phone_re.search(field_data): 205 raise ValidationError, _('Phone numbers must be in XXX-XXX-XXXX format. "%s" is invalid.') % field_data 206 207 def isValidQuicktimeVideoURL(field_data, all_data): 208 "Checks that the given URL is a video that can be played by QuickTime (qt, mpeg)" 209 uc = URLMimeTypeCheck(('video/quicktime', 'video/mpeg',)) 210 try: 211 uc(field_data, all_data) 212 except URLMimeTypeCheck.InvalidContentType: 213 raise ValidationError, _("The URL %s does not point to a valid QuickTime video.") % field_data 214 215 def isValidURL(field_data, all_data): 216 if not url_re.search(field_data): 217 raise ValidationError, _("A valid URL is required.") 218 219 def isValidHTML(field_data, all_data): 220 import urllib, urllib2 221 try: 222 u = urllib2.urlopen('http://validator.w3.org/check', urllib.urlencode({'fragment': field_data, 'output': 'xml'})) 223 except: 224 # Validator or Internet connection is unavailable. Fail silently. 225 return 226 html_is_valid = (u.headers.get('x-w3c-validator-status', 'Invalid') == 'Valid') 227 if html_is_valid: 228 return 229 from xml.dom.minidom import parseString 230 error_messages = [e.firstChild.wholeText for e in parseString(u.read()).getElementsByTagName('messages')[0].getElementsByTagName('msg')] 231 raise ValidationError, _("Valid HTML is required. Specific errors are:\n%s") % "\n".join(error_messages) 232 233 def isWellFormedXml(field_data, all_data): 234 from xml.dom.minidom import parseString 235 try: 236 parseString(field_data) 237 except Exception, e: # Naked except because we're not sure what will be thrown 238 raise ValidationError, _("Badly formed XML: %s") % str(e) 239 240 def isWellFormedXmlFragment(field_data, all_data): 241 isWellFormedXml('<root>%s</root>' % field_data, all_data) 242 243 def isExistingURL(field_data, all_data): 244 try: 245 headers = { 246 "Accept" : "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5", 247 "Accept-Language" : "en-us,en;q=0.5", 248 "Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", 249 "Connection" : "close", 250 "User-Agent": settings.URL_VALIDATOR_USER_AGENT 251 } 252 req = urllib2.Request(field_data,None, headers) 253 u = urllib2.urlopen(req) 254 except ValueError: 255 raise ValidationError, _("Invalid URL: %s") % field_data 256 except urllib2.HTTPError, e: 257 # 401s are valid; they just mean authorization is required. 258 # 301 and 302 are redirects; they just mean look somewhere else. 259 if str(e.code) not in ('401','301','302'): 260 raise ValidationError, _("The URL %s is a broken link.") % field_data 261 except: # urllib2.URLError, httplib.InvalidURL, etc. 262 raise ValidationError, _("The URL %s is a broken link.") % field_data 263 264 def isValidUSState(field_data, all_data): 265 "Checks that the given string is a valid two-letter U.S. state abbreviation" 266 states = ['AA', 'AE', 'AK', 'AL', 'AP', 'AR', 'AS', 'AZ', 'CA', 'CO', 'CT', 'DC', 'DE', 'FL', 'FM', 'GA', 'GU', 'HI', 'IA', 'ID', 'IL', 'IN', 'KS', 'KY', 'LA', 'MA', 'MD', 'ME', 'MH', 'MI', 'MN', 'MO', 'MP', 'MS', 'MT', 'NC', 'ND', 'NE', 'NH', 'NJ', 'NM', 'NV', 'NY', 'OH', 'OK', 'OR', 'PA', 'PR', 'PW', 'RI', 'SC', 'SD', 'TN', 'TX', 'UT', 'VA', 'VI', 'VT', 'WA', 'WI', 'WV', 'WY'] 267 if field_data.upper() not in states: 268 raise ValidationError, _("Enter a valid U.S. state abbreviation.") 269 270 def hasNoProfanities(field_data, all_data): 271 """ 272 Checks that the given string has no profanities in it. This does a simple 273 check for whether each profanity exists within the string, so 'fuck' will 274 catch 'motherfucker' as well. Raises a ValidationError such as: 275 Watch your mouth! The words "f--k" and "s--t" are not allowed here. 276 """ 277 field_data = field_data.lower() # normalize 278 words_seen = [w for w in settings.PROFANITIES_LIST if w in field_data] 279 if words_seen: 280 from django.utils.text import get_text_list 281 plural = len(words_seen) 282 raise ValidationError, ungettext("Watch your mouth! The word %s is not allowed here.", 283 "Watch your mouth! The words %s are not allowed here.", plural) % \ 284 get_text_list(['"%s%s%s"' % (i[0], '-'*(len(i)-2), i[-1]) for i in words_seen], _('and')) 285 286 class AlwaysMatchesOtherField(object): 287 def __init__(self, other_field_name, error_message=None): 288 self.other = other_field_name 289 self.error_message = error_message or lazy_inter(ugettext_lazy("This field must match the '%s' field."), self.other) 290 self.always_test = True 291 292 def __call__(self, field_data, all_data): 293 if field_data != all_data[self.other]: 294 raise ValidationError, self.error_message 295 296 class ValidateIfOtherFieldEquals(object): 297 def __init__(self, other_field, other_value, validator_list): 298 self.other_field, self.other_value = other_field, other_value 299 self.validator_list = validator_list 300 self.always_test = True 301 302 def __call__(self, field_data, all_data): 303 if self.other_field in all_data and all_data[self.other_field] == self.other_value: 304 for v in self.validator_list: 305 v(field_data, all_data) 306 307 class RequiredIfOtherFieldNotGiven(object): 308 def __init__(self, other_field_name, error_message=ugettext_lazy("Please enter something for at least one field.")): 309 self.other, self.error_message = other_field_name, error_message 310 self.always_test = True 311 312 def __call__(self, field_data, all_data): 313 if not all_data.get(self.other, False) and not field_data: 314 raise ValidationError, self.error_message 315 316 class RequiredIfOtherFieldsGiven(object): 317 def __init__(self, other_field_names, error_message=ugettext_lazy("Please enter both fields or leave them both empty.")): 318 self.other, self.error_message = other_field_names, error_message 319 self.always_test = True 320 321 def __call__(self, field_data, all_data): 322 for field in self.other: 323 if all_data.get(field, False) and not field_data: 324 raise ValidationError, self.error_message 325 326 class RequiredIfOtherFieldGiven(RequiredIfOtherFieldsGiven): 327 "Like RequiredIfOtherFieldsGiven, but takes a single field name instead of a list." 328 def __init__(self, other_field_name, error_message=ugettext_lazy("Please enter both fields or leave them both empty.")): 329 RequiredIfOtherFieldsGiven.__init__(self, [other_field_name], error_message) 330 331 class RequiredIfOtherFieldEquals(object): 332 def __init__(self, other_field, other_value, error_message=None, other_label=None): 333 self.other_field = other_field 334 self.other_value = other_value 335 other_label = other_label or other_value 336 self.error_message = error_message or lazy_inter(ugettext_lazy("This field must be given if %(field)s is %(value)s"), { 337 'field': other_field, 'value': other_label}) 338 self.always_test = True 339 340 def __call__(self, field_data, all_data): 341 if self.other_field in all_data and all_data[self.other_field] == self.other_value and not field_data: 342 raise ValidationError(self.error_message) 343 344 class RequiredIfOtherFieldDoesNotEqual(object): 345 def __init__(self, other_field, other_value, other_label=None, error_message=None): 346 self.other_field = other_field 347 self.other_value = other_value 348 other_label = other_label or other_value 349 self.error_message = error_message or lazy_inter(ugettext_lazy("This field must be given if %(field)s is not %(value)s"), { 350 'field': other_field, 'value': other_label}) 351 self.always_test = True 352 353 def __call__(self, field_data, all_data): 354 if self.other_field in all_data and all_data[self.other_field] != self.other_value and not field_data: 355 raise ValidationError(self.error_message) 356 357 class IsLessThanOtherField(object): 358 def __init__(self, other_field_name, error_message): 359 self.other, self.error_message = other_field_name, error_message 360 361 def __call__(self, field_data, all_data): 362 if field_data > all_data[self.other]: 363 raise ValidationError, self.error_message 364 365 class UniqueAmongstFieldsWithPrefix(object): 366 def __init__(self, field_name, prefix, error_message): 367 self.field_name, self.prefix = field_name, prefix 368 self.error_message = error_message or ugettext_lazy("Duplicate values are not allowed.") 369 370 def __call__(self, field_data, all_data): 371 for field_name, value in all_data.items(): 372 if field_name != self.field_name and value == field_data: 373 raise ValidationError, self.error_message 374 375 class NumberIsInRange(object): 376 """ 377 Validator that tests if a value is in a range (inclusive). 378 """ 379 def __init__(self, lower=None, upper=None, error_message=''): 380 self.lower, self.upper = lower, upper 381 if not error_message: 382 if lower and upper: 383 self.error_message = _("This value must be between %(lower)s and %(upper)s.") % {'lower': lower, 'upper': upper} 384 elif lower: 385 self.error_message = _("This value must be at least %s.") % lower 386 elif upper: 387 self.error_message = _("This value must be no more than %s.") % upper 388 else: 389 self.error_message = error_message 390 391 def __call__(self, field_data, all_data): 392 # Try to make the value numeric. If this fails, we assume another 393 # validator will catch the problem. 394 try: 395 val = float(field_data) 396 except ValueError: 397 return 398 399 # Now validate 400 if self.lower and self.upper and (val < self.lower or val > self.upper): 401 raise ValidationError(self.error_message) 402 elif self.lower and val < self.lower: 403 raise ValidationError(self.error_message) 404 elif self.upper and val > self.upper: 405 raise ValidationError(self.error_message) 406 407 class IsAPowerOf(object): 408 """ 409 Usage: If you create an instance of the IsPowerOf validator: 410 v = IsAPowerOf(2) 411 412 The following calls will succeed: 413 v(4, None) 414 v(8, None) 415 v(16, None) 416 417 But this call: 418 v(17, None) 419 will raise "django.core.validators.ValidationError: ['This value must be a power of 2.']" 420 """ 421 def __init__(self, power_of): 422 self.power_of = power_of 423 424 def __call__(self, field_data, all_data): 425 from math import log 426 val = log(int(field_data)) / log(self.power_of) 427 if val != int(val): 428 raise ValidationError, _("This value must be a power of %s.") % self.power_of 429 430 class IsValidDecimal(object): 431 def __init__(self, max_digits, decimal_places): 432 self.max_digits, self.decimal_places = max_digits, decimal_places 433 434 def __call__(self, field_data, all_data): 435 try: 436 val = Decimal(field_data) 437 except DecimalException: 438 raise ValidationError, _("Please enter a valid decimal number.") 439 440 pieces = str(val).lstrip("-").split('.') 441 decimals = (len(pieces) == 2) and len(pieces[1]) or 0 442 digits = len(pieces[0]) 443 444 if digits + decimals > self.max_digits: 445 raise ValidationError, ungettext("Please enter a valid decimal number with at most %s total digit.", 446 "Please enter a valid decimal number with at most %s total digits.", self.max_digits) % self.max_digits 447 if digits > (self.max_digits - self.decimal_places): 448 raise ValidationError, ungettext( "Please enter a valid decimal number with a whole part of at most %s digit.", 449 "Please enter a valid decimal number with a whole part of at most %s digits.", str(self.max_digits-self.decimal_places)) % str(self.max_digits-self.decimal_places) 450 if decimals > self.decimal_places: 451 raise ValidationError, ungettext("Please enter a valid decimal number with at most %s decimal place.", 452 "Please enter a valid decimal number with at most %s decimal places.", self.decimal_places) % self.decimal_places 453 454 def isValidFloat(field_data, all_data): 455 data = smart_str(field_data) 456 try: 457 float(data) 458 except ValueError: 459 raise ValidationError, _("Please enter a valid floating point number.") 460 461 class HasAllowableSize(object): 462 """ 463 Checks that the file-upload field data is a certain size. min_size and 464 max_size are measurements in bytes. 465 """ 466 def __init__(self, min_size=None, max_size=None, min_error_message=None, max_error_message=None): 467 self.min_size, self.max_size = min_size, max_size 468 self.min_error_message = min_error_message or lazy_inter(ugettext_lazy("Make sure your uploaded file is at least %s bytes big."), min_size) 469 self.max_error_message = max_error_message or lazy_inter(ugettext_lazy("Make sure your uploaded file is at most %s bytes big."), max_size) 470 471 def __call__(self, field_data, all_data): 472 try: 473 content = field_data.read() 474 except TypeError: 475 raise ValidationError, ugettext_lazy("No file was submitted. Check the encoding type on the form.") 476 if self.min_size is not None and len(content) < self.min_size: 477 raise ValidationError, self.min_error_message 478 if self.max_size is not None and len(content) > self.max_size: 479 raise ValidationError, self.max_error_message 480 481 class MatchesRegularExpression(object): 482 """ 483 Checks that the field matches the given regular-expression. The regex 484 should be in string format, not already compiled. 485 """ 486 def __init__(self, regexp, error_message=ugettext_lazy("The format for this field is wrong.")): 487 self.regexp = re.compile(regexp) 488 self.error_message = error_message 489 490 def __call__(self, field_data, all_data): 491 if not self.regexp.search(field_data): 492 raise ValidationError(self.error_message) 493 494 class AnyValidator(object): 495 """ 496 This validator tries all given validators. If any one of them succeeds, 497 validation passes. If none of them succeeds, the given message is thrown 498 as a validation error. The message is rather unspecific, so it's best to 499 specify one on instantiation. 500 """ 501 def __init__(self, validator_list=None, error_message=ugettext_lazy("This field is invalid.")): 502 if validator_list is None: validator_list = [] 503 self.validator_list = validator_list 504 self.error_message = error_message 505 for v in validator_list: 506 if hasattr(v, 'always_test'): 507 self.always_test = True 508 509 def __call__(self, field_data, all_data): 510 for v in self.validator_list: 511 try: 512 v(field_data, all_data) 513 return 514 except ValidationError, e: 515 pass 516 raise ValidationError(self.error_message) 517 518 class URLMimeTypeCheck(object): 519 "Checks that the provided URL points to a document with a listed mime type" 520 class CouldNotRetrieve(ValidationError): 521 pass 522 class InvalidContentType(ValidationError): 523 pass 524 525 def __init__(self, mime_type_list): 526 self.mime_type_list = mime_type_list 527 528 def __call__(self, field_data, all_data): 529 import urllib2 530 try: 531 isValidURL(field_data, all_data) 532 except ValidationError: 533 raise 534 try: 535 info = urllib2.urlopen(field_data).info() 536 except (urllib2.HTTPError, urllib2.URLError): 537 raise URLMimeTypeCheck.CouldNotRetrieve, _("Could not retrieve anything from %s.") % field_data 538 content_type = info['content-type'] 539 if content_type not in self.mime_type_list: 540 raise URLMimeTypeCheck.InvalidContentType, _("The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'.") % { 541 'url': field_data, 'contenttype': content_type} 542 543 class RelaxNGCompact(object): 544 "Validate against a Relax NG compact schema" 545 def __init__(self, schema_path, additional_root_element=None): 546 self.schema_path = schema_path 547 self.additional_root_element = additional_root_element 548 549 def __call__(self, field_data, all_data): 550 import os, tempfile 551 if self.additional_root_element: 552 field_data = '<%(are)s>%(data)s\n</%(are)s>' % { 553 'are': self.additional_root_element, 554 'data': field_data 555 } 556 filename = tempfile.mktemp() # Insecure, but nothing else worked 557 fp = open(filename, 'w') 558 fp.write(field_data) 559 fp.close() 560 if not os.path.exists(settings.JING_PATH): 561 raise Exception, "%s not found!" % settings.JING_PATH 562 p = os.popen('%s -c %s %s' % (settings.JING_PATH, self.schema_path, filename)) 563 errors = [line.strip() for line in p.readlines()] 564 p.close() 565 os.unlink(filename) 566 display_errors = [] 567 lines = field_data.split('\n') 568 for error in errors: 569 ignored, line, level, message = error.split(':', 3) 570 # Scrape the Jing error messages to reword them more nicely. 571 m = re.search(r'Expected "(.*?)" to terminate element starting on line (\d+)', message) 572 if m: 573 display_errors.append(_('Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with "%(start)s".)') % \ 574 {'tag':m.group(1).replace('/', ''), 'line':m.group(2), 'start':lines[int(m.group(2)) - 1][:30]}) 575 continue 576 if message.strip() == 'text not allowed here': 577 display_errors.append(_('Some text starting on line %(line)s is not allowed in that context. (Line starts with "%(start)s".)') % \ 578 {'line':line, 'start':lines[int(line) - 1][:30]}) 579 continue 580 m = re.search(r'\s*attribute "(.*?)" not allowed at this point; ignored', message) 581 if m: 582 display_errors.append(_('"%(attr)s" on line %(line)s is an invalid attribute. (Line starts with "%(start)s".)') % \ 583 {'attr':m.group(1), 'line':line, 'start':lines[int(line) - 1][:30]}) 584 continue 585 m = re.search(r'\s*unknown element "(.*?)"', message) 586 if m: 587 display_errors.append(_('"<%(tag)s>" on line %(line)s is an invalid tag. (Line starts with "%(start)s".)') % \ 588 {'tag':m.group(1), 'line':line, 'start':lines[int(line) - 1][:30]}) 589 continue 590 if message.strip() == 'required attributes missing': 591 display_errors.append(_('A tag on line %(line)s is missing one or more required attributes. (Line starts with "%(start)s".)') % \ 592 {'line':line, 'start':lines[int(line) - 1][:30]}) 593 continue 594 m = re.search(r'\s*bad value for attribute "(.*?)"', message) 595 if m: 596 display_errors.append(_('The "%(attr)s" attribute on line %(line)s has an invalid value. (Line starts with "%(start)s".)') % \ 597 {'attr':m.group(1), 'line':line, 'start':lines[int(line) - 1][:30]}) 598 continue 599 # Failing all those checks, use the default error message. 600 display_error = 'Line %s: %s [%s]' % (line, message, level.strip()) 601 display_errors.append(display_error) 602 if len(display_errors) > 0: 603 raise ValidationError, display_errors -
tests/modeltests/manipulators/models.py
diff --git a/tests/modeltests/manipulators/models.py b/tests/modeltests/manipulators/models.py index 3e52e33..64cfbd3 100644
a b True 99 99 datetime.date(2005, 2, 13) 100 100 101 101 # Test isValidFloat Unicode coercion 102 >>> from django. core.validators import isValidFloat, ValidationError102 >>> from django.oldforms.validators import isValidFloat, ValidationError 103 103 >>> try: isValidFloat(u"ä", None) 104 104 ... except ValidationError: pass 105 105 """} -
tests/modeltests/model_forms/models.py
diff --git a/tests/modeltests/model_forms/models.py b/tests/modeltests/model_forms/models.py index be2a8ba..9d8f4ea 100644
a b Create a new article, with categories, via the form. 487 487 ... model = Article 488 488 >>> f = ArticleForm({'headline': u'The walrus was Paul', 'slug': u'walrus-was-paul', 'pub_date': u'1967-11-01', 489 489 ... 'writer': u'1', 'article': u'Test.', 'categories': [u'1', u'2']}) 490 >>> f.is_valid() 491 True 490 492 >>> new_art = f.save() 491 493 >>> new_art.id 492 494 2 … … u'...test2.txt' 861 863 >>> instance.delete() 862 864 863 865 # Test the non-required FileField 864 866 # It should fail since the field IS required on the model 865 867 >>> f = TextFileForm(data={'description': u'Assistance'}) 866 868 >>> f.fields['file'].required = False 867 869 >>> f.is_valid() 868 True 869 >>> instance = f.save() 870 >>> instance.file 871 '' 870 False 871 >>> f.errors 872 {'file': [u'This field is required.']} 872 873 873 874 >>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': SimpleUploadedFile('test3.txt', 'hello world')}, instance=instance) 874 875 >>> f.is_valid() … … u'...test2.png' 970 971 >>> f = ImageFileForm(data={'description': u'Test'}) 971 972 >>> f.fields['image'].required = False 972 973 >>> f.is_valid() 973 True974 >>> instance = f.save()975 >>> instance.image 976 '' 974 False 975 >>> f.errors 976 {'image': [u'This field is required.']} 977 977 978 978 979 >>> f = ImageFileForm(data={'description': u'And a final one'}, files={'image': SimpleUploadedFile('test3.png', image_data)}, instance=instance) 979 980 >>> f.is_valid() -
tests/modeltests/validation/models.py
diff --git a/tests/modeltests/validation/models.py b/tests/modeltests/validation/models.py index 63f9f7a..7d558ff 100644
a b 3 3 4 4 This is an experimental feature! 5 5 6 Each model instance has a validate() method that returns a dictionary of6 Each model instance has a clean() method that returns a dictionary of 7 7 validation errors in the instance's fields. This method has a side effect 8 8 of converting each field to its appropriate Python data type. 9 9 """ … … class Person(models.Model): 15 15 name = models.CharField(max_length=20) 16 16 birthdate = models.DateField() 17 17 favorite_moment = models.DateTimeField() 18 email = models.EmailField() 19 18 email = models.EmailField(unique=True) 19 20 class Meta: 21 unique_together = (('name', 'is_child'),) 20 22 def __unicode__(self): 21 23 return self.name 22 24 … … __test__ = {'API_TESTS':""" 30 32 ... 'favorite_moment': datetime.datetime(2002, 4, 3, 13, 23), 31 33 ... 'email': 'john@example.com' 32 34 ... } 33 >>> p = Person(**valid_params) 34 >>> p.validate() 35 {} 36 37 >>> p = Person(**dict(valid_params, id='23')) 38 >>> p.validate() 39 {} 35 >>> p = Person(**dict(valid_params, email='john@e.com', name='Jack')) 36 >>> p.clean() 37 >>> p.save() 38 39 >>> p = Person(**dict(valid_params, email='john@e.com')) 40 >>> p.clean() 41 Traceback (most recent call last): 42 ... 43 ValidationError: {'email': [u'This field must be unique']} 44 45 >>> p = Person(**dict(valid_params, id='23', name='Jack')) 46 >>> p.clean() 47 Traceback (most recent call last): 48 ... 49 ValidationError: {'__all__': u'Fields name, is_child must be unique.'} 40 50 >>> p.id 41 51 23 42 52 43 >>> p = Person(**dict(valid_params, id='foo')) 44 >>> p.validate()['id'] 45 [u'This value must be an integer.'] 53 # when type coercion fails, no other validation is done 54 >>> p = Person(**dict(valid_params, email='john@e.com', id='foo')) 55 >>> p.clean() 56 Traceback (most recent call last): 57 ... 58 ValidationError: {'id': [u'This value must be an integer.']} 46 59 47 60 >>> p = Person(**dict(valid_params, id=None)) 48 >>> p.validate() 49 {} 61 >>> p.clean() 50 62 >>> repr(p.id) 51 63 'None' 52 64 53 65 >>> p = Person(**dict(valid_params, is_child='t')) 54 >>> p.validate() 55 {} 66 >>> p.clean() 56 67 >>> p.is_child 57 68 True 58 69 59 70 >>> p = Person(**dict(valid_params, is_child='f')) 60 >>> p.validate() 61 {} 71 >>> p.clean() 62 72 >>> p.is_child 63 73 False 64 74 65 75 >>> p = Person(**dict(valid_params, is_child=True)) 66 >>> p.validate() 67 {} 76 >>> p.clean() 68 77 >>> p.is_child 69 78 True 70 79 71 80 >>> p = Person(**dict(valid_params, is_child=False)) 72 >>> p.validate() 73 {} 81 >>> p.clean() 74 82 >>> p.is_child 75 83 False 76 84 77 85 >>> p = Person(**dict(valid_params, is_child='foo')) 78 >>> p.validate()['is_child'] 79 [u'This value must be either True or False.'] 86 >>> p.clean() 87 Traceback (most recent call last): 88 ... 89 ValidationError: {'is_child': [u'This value must be either True or False.']} 80 90 81 91 >>> p = Person(**dict(valid_params, name=u'Jose')) 82 >>> p.validate() 83 {} 92 >>> p.clean() 84 93 >>> p.name 85 94 u'Jose' 86 95 87 96 >>> p = Person(**dict(valid_params, name=227)) 88 >>> p.validate() 89 {} 97 >>> p.clean() 90 98 >>> p.name 91 99 u'227' 92 100 93 101 >>> p = Person(**dict(valid_params, birthdate=datetime.date(2000, 5, 3))) 94 >>> p.validate() 95 {} 102 >>> p.clean() 96 103 >>> p.birthdate 97 104 datetime.date(2000, 5, 3) 98 105 99 106 >>> p = Person(**dict(valid_params, birthdate=datetime.datetime(2000, 5, 3))) 100 >>> p.validate() 101 {} 107 >>> p.clean() 102 108 >>> p.birthdate 103 109 datetime.date(2000, 5, 3) 104 110 105 111 >>> p = Person(**dict(valid_params, birthdate='2000-05-03')) 106 >>> p.validate() 107 {} 112 >>> p.clean() 108 113 >>> p.birthdate 109 114 datetime.date(2000, 5, 3) 110 115 111 116 >>> p = Person(**dict(valid_params, birthdate='2000-5-3')) 112 >>> p.validate() 113 {} 117 >>> p.clean() 114 118 >>> p.birthdate 115 119 datetime.date(2000, 5, 3) 116 120 117 121 >>> p = Person(**dict(valid_params, birthdate='foo')) 118 >>> p.validate()['birthdate'] 119 [u'Enter a valid date in YYYY-MM-DD format.'] 122 >>> p.clean() 123 Traceback (most recent call last): 124 ... 125 ValidationError: {'birthdate': [u'Enter a valid date in YYYY-MM-DD format.']} 120 126 121 127 >>> p = Person(**dict(valid_params, favorite_moment=datetime.datetime(2002, 4, 3, 13, 23))) 122 >>> p.validate() 123 {} 128 >>> p.clean() 124 129 >>> p.favorite_moment 125 130 datetime.datetime(2002, 4, 3, 13, 23) 126 131 127 132 >>> p = Person(**dict(valid_params, favorite_moment=datetime.datetime(2002, 4, 3))) 128 >>> p.validate() 129 {} 133 >>> p.clean() 130 134 >>> p.favorite_moment 131 135 datetime.datetime(2002, 4, 3, 0, 0) 132 136 133 137 >>> p = Person(**dict(valid_params, email='john@example.com')) 134 >>> p.validate() 135 {} 138 >>> p.clean() 136 139 >>> p.email 137 140 'john@example.com' 138 141 139 142 >>> p = Person(**dict(valid_params, email=u'john@example.com')) 140 >>> p.validate() 141 {} 143 >>> p.clean() 142 144 >>> p.email 143 145 u'john@example.com' 144 146 145 147 >>> p = Person(**dict(valid_params, email=22)) 146 >>> p.validate()['email'] 147 [u'Enter a valid e-mail address.'] 148 >>> p.clean() 149 Traceback (most recent call last): 150 ... 151 ValidationError: {'email': [u'Enter a valid e-mail address.']} 148 152 149 153 # Make sure that Date and DateTime return validation errors and don't raise Python errors. 150 >>> p = Person(name='John Doe', is_child=True, email='abc@def.com') 151 >>> errors = p.validate() 152 >>> errors['favorite_moment'] 154 >>> from django.core.exceptions import ValidationError 155 >>> try: 156 ... Person(name='John Doe', is_child=True, email='abc@def.com').clean() 157 ... except ValidationError, e: 158 ... e.message_dict['favorite_moment'] 159 ... e.message_dict['birthdate'] 153 160 [u'This field is required.'] 154 >>> errors['birthdate']155 161 [u'This field is required.'] 156 162 157 163 """} -
new file tests/regressiontests/core/models.py
diff --git a/tests/regressiontests/core/__init__.py b/tests/regressiontests/core/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/regressiontests/core/models.py b/tests/regressiontests/core/models.py new file mode 100644 index 0000000..e5a7950
- + 1 # A models.py so that tests run. 2 -
new file tests/regressiontests/core/tests.py
diff --git a/tests/regressiontests/core/tests.py b/tests/regressiontests/core/tests.py new file mode 100644 index 0000000..adc72df
- + 1 tests = r""" 2 ################### 3 # ValidationError # 4 ################### 5 >>> from django.core.exceptions import ValidationError 6 >>> from django.utils.translation import ugettext_lazy 7 8 # Can take a string. 9 >>> print ValidationError("There was an error.").messages 10 <ul class="errorlist"><li>There was an error.</li></ul> 11 12 # Can take a unicode string. 13 >>> print ValidationError(u"Not \u03C0.").messages 14 <ul class="errorlist"><li>Not π.</li></ul> 15 16 # Can take a lazy string. 17 >>> print ValidationError(ugettext_lazy("Error.")).messages 18 <ul class="errorlist"><li>Error.</li></ul> 19 20 # Can take a list. 21 >>> print ValidationError(["Error one.", "Error two."]).messages 22 <ul class="errorlist"><li>Error one.</li><li>Error two.</li></ul> 23 24 # Can take a mixture in a list. 25 >>> print ValidationError(["First error.", u"Not \u03C0.", ugettext_lazy("Error.")]).messages 26 <ul class="errorlist"><li>First error.</li><li>Not π.</li><li>Error.</li></ul> 27 28 >>> class VeryBadError: 29 ... def __unicode__(self): return u"A very bad error." 30 31 # Can take a non-string. 32 >>> print ValidationError(VeryBadError()).messages 33 <ul class="errorlist"><li>A very bad error.</li></ul> 34 """ 35 -
tests/regressiontests/forms/error_messages.py
diff --git a/tests/regressiontests/forms/error_messages.py b/tests/regressiontests/forms/error_messages.py index ec91b57..9b35551 100644
a b ValidationError: [u'LENGTH 11, MAX LENGTH 10'] 204 204 205 205 >>> e = {'required': 'REQUIRED'} 206 206 >>> e['invalid'] = 'INVALID' 207 >>> e['missing'] = 'MISSING'208 207 >>> e['empty'] = 'EMPTY FILE' 209 208 >>> f = FileField(error_messages=e) 210 209 >>> f.clean('') 211 210 Traceback (most recent call last): 212 211 ... 213 ValidationError: [u' REQUIRED']212 ValidationError: [u'INVALID'] 214 213 >>> f.clean('abc') 215 214 Traceback (most recent call last): 216 215 ... 217 216 ValidationError: [u'INVALID'] 218 >>> f.clean( SimpleUploadedFile('name', None))217 >>> f.clean({}) 219 218 Traceback (most recent call last): 220 219 ... 221 ValidationError: [u' EMPTY FILE']222 >>> f.clean( SimpleUploadedFile('name', ''))220 ValidationError: [u'INVALID'] 221 >>> f.clean({'filename': 'name', 'content':''}) 223 222 Traceback (most recent call last): 224 223 ... 225 224 ValidationError: [u'EMPTY FILE'] -
tests/regressiontests/forms/fields.py
diff --git a/tests/regressiontests/forms/fields.py b/tests/regressiontests/forms/fields.py index 53364b8..34e96fe 100644
a b Each Field's __init__() takes at least these parameters: 32 32 field name, if the Field is part of a Form. 33 33 initial -- A value to use in this Field's initial display. This value is 34 34 *not* used as a fallback if data isn't given. 35 validators -- Optional list of additional validator functions 35 36 36 37 Other than that, the Field subclasses have class-specific options for 37 38 __init__(). For example, CharField has a max_length option. … … u'1234567890' 104 105 >>> f.clean('1234567890a') 105 106 u'1234567890a' 106 107 108 # Custom validator functions ################################################## 109 110 >>> def validator(value, error_dict={}): raise ValidationError('validator failed') 111 >>> f = CharField(min_length=10, validators=[validator]) 112 >>> f.clean('aa') 113 Traceback (most recent call last): 114 ... 115 ValidationError: [u'validator failed'] 116 117 >>> def validator2(value, error_dict={}): raise ValidationError('validator2 failed') 118 >>> f = CharField(min_length=10, validators=[validator, validator, validator2]) 119 >>> f.clean('aa') 120 Traceback (most recent call last): 121 ... 122 ValidationError: [u'validator failed', u'validator failed', u'validator2 failed'] 123 124 >>> class MyCharField(CharField): 125 ... validators = [validator] 126 >>> f = MyCharField() 127 >>> f.clean('aa') 128 Traceback (most recent call last): 129 ... 130 ValidationError: [u'validator failed'] 131 107 132 # IntegerField ################################################################ 108 133 109 134 >>> f = IntegerField() … … ValidationError: [u'Ensure this value has at most 15 characters (it has 20).'] 748 773 >>> f.clean('') 749 774 Traceback (most recent call last): 750 775 ... 751 ValidationError: [u' This field is required.']776 ValidationError: [u'No file was submitted. Check the encoding type on the form.'] 752 777 753 778 >>> f.clean('', '') 754 779 Traceback (most recent call last): 755 780 ... 756 ValidationError: [u' This field is required.']781 ValidationError: [u'No file was submitted. Check the encoding type on the form.'] 757 782 758 783 >>> f.clean('', 'files/test1.pdf') 759 784 'files/test1.pdf' … … ValidationError: [u'This field is required.'] 761 786 >>> f.clean(None) 762 787 Traceback (most recent call last): 763 788 ... 764 ValidationError: [u' This field is required.']789 ValidationError: [u'No file was submitted. Check the encoding type on the form.'] 765 790 766 791 >>> f.clean(None, '') 767 792 Traceback (most recent call last): 768 793 ... 769 ValidationError: [u' This field is required.']794 ValidationError: [u'No file was submitted. Check the encoding type on the form.'] 770 795 771 796 >>> f.clean(None, 'files/test2.pdf') 772 797 'files/test2.pdf' … … ValidationError: [u'Select a valid choice. 3 is not one of the available choices 1012 1037 1013 1038 >>> f = ChoiceField(choices=[('1', 'One'), ('2', 'Two')], required=False) 1014 1039 >>> f.clean('') 1015 u''1016 1040 >>> f.clean(None) 1017 u''1018 1041 >>> f.clean(1) 1019 1042 u'1' 1020 1043 >>> f.clean('1') -
tests/regressiontests/forms/forms.py
diff --git a/tests/regressiontests/forms/forms.py b/tests/regressiontests/forms/forms.py index d834bda..0a9253f 100644
a b not request.POST. 1464 1464 1465 1465 >>> f = FileForm(data={}, files={}, auto_id=False) 1466 1466 >>> print f 1467 <tr><th>File1:</th><td><ul class="errorlist"><li> This field is required.</li></ul><input type="file" name="file1" /></td></tr>1467 <tr><th>File1:</th><td><ul class="errorlist"><li>No file was submitted. Check the encoding type on the form.</li></ul><input type="file" name="file1" /></td></tr> 1468 1468 1469 1469 >>> f = FileForm(data={}, files={'file1': SimpleUploadedFile('name', '')}, auto_id=False) 1470 1470 >>> print f -
tests/regressiontests/forms/localflavor/br.py
diff --git a/tests/regressiontests/forms/localflavor/br.py b/tests/regressiontests/forms/localflavor/br.py index 757f382..94285c3 100644
a b Traceback (most recent call last): 85 85 ... 86 86 ValidationError: [u'Invalid CNPJ number.'] 87 87 >>> f.clean('64.132.916/0001-88') 88 '64.132.916/0001-88'88 u'64.132.916/0001-88' 89 89 >>> f.clean('64-132-916/0001-88') 90 '64-132-916/0001-88'90 u'64-132-916/0001-88' 91 91 >>> f.clean('64132916/0001-88') 92 '64132916/0001-88'92 u'64132916/0001-88' 93 93 >>> f.clean('64.132.916/0001-XX') 94 94 Traceback (most recent call last): 95 95 ... -
tests/regressiontests/forms/util.py
diff --git a/tests/regressiontests/forms/util.py b/tests/regressiontests/forms/util.py index 68c082c..5272b2c 100644
a b u' id="header"' 18 18 u' class="news" title="Read this"' 19 19 >>> flatatt({}) 20 20 u'' 21 22 ###################23 # ValidationError #24 ###################25 26 # Can take a string.27 >>> print ValidationError("There was an error.").messages28 <ul class="errorlist"><li>There was an error.</li></ul>29 30 # Can take a unicode string.31 >>> print ValidationError(u"Not \u03C0.").messages32 <ul class="errorlist"><li>Not π.</li></ul>33 34 # Can take a lazy string.35 >>> print ValidationError(ugettext_lazy("Error.")).messages36 <ul class="errorlist"><li>Error.</li></ul>37 38 # Can take a list.39 >>> print ValidationError(["Error one.", "Error two."]).messages40 <ul class="errorlist"><li>Error one.</li><li>Error two.</li></ul>41 42 # Can take a mixture in a list.43 >>> print ValidationError(["First error.", u"Not \u03C0.", ugettext_lazy("Error.")]).messages44 <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()).messages51 <ul class="errorlist"><li>A very bad error.</li></ul>52 21 """