mirror of
				https://github.com/django/django.git
				synced 2025-10-30 09:06:13 +00:00 
			
		
		
		
	Fixed #5871 -- Factored out the validation errors in localflavor form fields. Brings them into line with the standard newforms fields. Patch from Jan Rademaker.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@6926 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
		| @@ -24,18 +24,20 @@ class ARPostalCodeField(RegexField): | ||||
|  | ||||
|     See http://www.correoargentino.com.ar/consulta_cpa/home.php | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': ugettext("Enter a postal code in the format NNNN or ANNNNAAA."), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(ARPostalCodeField, self).__init__(r'^\d{4}$|^[A-HJ-NP-Za-hj-np-z]\d{4}\D{3}$', | ||||
|             min_length=4, max_length=8, | ||||
|             error_message=ugettext("Enter a postal code in the format NNNN or ANNNNAAA."), | ||||
|                     *args, **kwargs) | ||||
|             min_length=4, max_length=8, *args, **kwargs) | ||||
|  | ||||
|     def clean(self, value): | ||||
|         value = super(ARPostalCodeField, self).clean(value) | ||||
|         if value in EMPTY_VALUES: | ||||
|             return u'' | ||||
|         if len(value) not in (4, 8): | ||||
|             raise ValidationError(ugettext("Enter a postal code in the format NNNN or ANNNNAAA.")) | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|         if len(value) == 8: | ||||
|             return u'%s%s%s' % (value[0].upper(), value[1:5], value[5:].upper()) | ||||
|         return value | ||||
| @@ -44,6 +46,11 @@ class ARDNIField(CharField): | ||||
|     """ | ||||
|     A field that validates `Documento Nacional de Identidad<61> (DNI) numbers. | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': ugettext("This field requires only numbers."), | ||||
|         'max_digits': ugettext("This field requires 7 or 8 digits."), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(ARDNIField, self).__init__(max_length=10, min_length=7, *args, | ||||
|                 **kwargs) | ||||
| @@ -58,10 +65,9 @@ class ARDNIField(CharField): | ||||
|         if not value.isdigit(): | ||||
|             value = value.replace('.', '') | ||||
|         if not value.isdigit(): | ||||
|             raise ValidationError(ugettext("This field requires only numbers.")) | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|         if len(value) not in (7, 8): | ||||
|             raise ValidationError( | ||||
|                     ugettext("This field requires 7 or 8 digits.")) | ||||
|             raise ValidationError(self.error_messages['max_digits']) | ||||
|  | ||||
|         return value | ||||
|  | ||||
| @@ -70,9 +76,13 @@ class ARCUITField(RegexField): | ||||
|     This field validates a CUIT (C<>digo <20>nico de Identificaci<63>n Tributaria). A | ||||
|     CUIT is of the form XX-XXXXXXXX-V. The last digit is a check digit. | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': ugettext('Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.'), | ||||
|         'checksum': ugettext("Invalid CUIT."), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(ARCUITField, self).__init__(r'^\d{2}-?\d{8}-?\d$', | ||||
|             error_message=ugettext('Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.'), | ||||
|             *args, **kwargs) | ||||
|  | ||||
|     def clean(self, value): | ||||
| @@ -85,7 +95,7 @@ class ARCUITField(RegexField): | ||||
|             return u'' | ||||
|         value, cd = self._canon(value) | ||||
|         if self._calc_cd(value) != cd: | ||||
|             raise ValidationError(ugettext("Invalid CUIT.")) | ||||
|             raise ValidationError(self.error_messages['checksum']) | ||||
|         return self._format(value, cd) | ||||
|  | ||||
|     def _canon(self, cuit): | ||||
|   | ||||
| @@ -12,14 +12,20 @@ PHONE_DIGITS_RE = re.compile(r'^(\d{10})$') | ||||
|  | ||||
| class AUPostCodeField(RegexField): | ||||
|     """Australian post code field.""" | ||||
|     default_error_messages = { | ||||
|         'invalid': ugettext('Enter a 4 digit post code.'), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(AUPostCodeField, self).__init__(r'^\d{4}$', | ||||
|             max_length=None, min_length=None, | ||||
|             error_message=ugettext('Enter a 4 digit post code.'), | ||||
|                     *args, **kwargs) | ||||
|             max_length=None, min_length=None, *args, **kwargs) | ||||
|  | ||||
| class AUPhoneNumberField(Field): | ||||
|     """Australian phone number field.""" | ||||
|     default_error_messages = { | ||||
|         'invalid': u'Phone numbers must contain 10 digits.', | ||||
|     } | ||||
|  | ||||
|     def clean(self, value): | ||||
|         """ | ||||
|         Validate a phone number. Strips parentheses, whitespace and hyphens. | ||||
| @@ -31,7 +37,7 @@ class AUPhoneNumberField(Field): | ||||
|         phone_match = PHONE_DIGITS_RE.search(value) | ||||
|         if phone_match: | ||||
|             return u'%s' % phone_match.group(1) | ||||
|         raise ValidationError(u'Phone numbers must contain 10 digits.') | ||||
|         raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
| class AUStateSelect(Select): | ||||
|     """ | ||||
|   | ||||
| @@ -17,13 +17,19 @@ except NameError: | ||||
| phone_digits_re = re.compile(r'^(\d{2})[-\.]?(\d{4})[-\.]?(\d{4})$') | ||||
|  | ||||
| class BRZipCodeField(RegexField): | ||||
|     default_error_messages = { | ||||
|         'invalid': _('Enter a zip code in the format XXXXX-XXX.'), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(BRZipCodeField, self).__init__(r'^\d{5}-\d{3}$', | ||||
|             max_length=None, min_length=None, | ||||
|             error_message=_('Enter a zip code in the format XXXXX-XXX.'), | ||||
|                     *args, **kwargs) | ||||
|             max_length=None, min_length=None, *args, **kwargs) | ||||
|  | ||||
| class BRPhoneNumberField(Field): | ||||
|     default_error_messages = { | ||||
|         'invalid': _('Phone numbers must be in XX-XXXX-XXXX format.'), | ||||
|     } | ||||
|  | ||||
|     def clean(self, value): | ||||
|         super(BRPhoneNumberField, self).clean(value) | ||||
|         if value in EMPTY_VALUES: | ||||
| @@ -32,7 +38,7 @@ class BRPhoneNumberField(Field): | ||||
|         m = phone_digits_re.search(value) | ||||
|         if m: | ||||
|             return u'%s-%s-%s' % (m.group(1), m.group(2), m.group(3)) | ||||
|         raise ValidationError(_('Phone numbers must be in XX-XXXX-XXXX format.')) | ||||
|         raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
| class BRStateSelect(Select): | ||||
|     """ | ||||
| @@ -48,6 +54,9 @@ class BRStateChoiceField(Field): | ||||
|     A choice field that uses a list of Brazilian states as its choices. | ||||
|     """ | ||||
|     widget = Select | ||||
|     default_error_messages = { | ||||
|         'invalid': _(u'Select a valid brazilian state. That state is not one of the available states.'), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, required=True, widget=None, label=None, | ||||
|                  initial=None, help_text=None): | ||||
| @@ -65,9 +74,7 @@ class BRStateChoiceField(Field): | ||||
|             return value | ||||
|         valid_values = set([smart_unicode(k) for k, v in self.widget.choices]) | ||||
|         if value not in valid_values: | ||||
|             raise ValidationError(_(u'Select a valid brazilian state.' | ||||
|                                            u' That state is not one' | ||||
|                                            u' of the available states.')) | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|         return value | ||||
|  | ||||
| def DV_maker(v): | ||||
| @@ -83,6 +90,12 @@ class BRCPFField(CharField): | ||||
|     More information: | ||||
|     http://en.wikipedia.org/wiki/Cadastro_de_Pessoas_F%C3%ADsicas | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': _("Invalid CPF number."), | ||||
|         'max_digits': _("This field requires at most 11 digits or 14 characters."), | ||||
|         'digits_only': _("This field requires only numbers."), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(BRCPFField, self).__init__(max_length=14, min_length=11, *args, **kwargs) | ||||
|  | ||||
| @@ -100,9 +113,9 @@ class BRCPFField(CharField): | ||||
|         try: | ||||
|             int(value) | ||||
|         except ValueError: | ||||
|             raise ValidationError(_("This field requires only numbers.")) | ||||
|             raise ValidationError(self.error_messages['digits_only']) | ||||
|         if len(value) != 11: | ||||
|             raise ValidationError(_("This field requires at most 11 digits or 14 characters.")) | ||||
|             raise ValidationError(self.error_messages['max_digits']) | ||||
|         orig_dv = value[-2:] | ||||
|  | ||||
|         new_1dv = sum([i * int(value[idx]) for idx, i in enumerate(range(10, 1, -1))]) | ||||
| @@ -112,11 +125,17 @@ class BRCPFField(CharField): | ||||
|         new_2dv = DV_maker(new_2dv % 11) | ||||
|         value = value[:-1] + str(new_2dv) | ||||
|         if value[-2:] != orig_dv: | ||||
|             raise ValidationError(_("Invalid CPF number.")) | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
|         return orig_value | ||||
|  | ||||
| class BRCNPJField(Field): | ||||
|     default_error_messages = { | ||||
|         'invalid': _("Invalid CNPJ number."), | ||||
|         'digits_only': _("This field requires only numbers."), | ||||
|         'max_digits': _("This field requires at least 14 digits"), | ||||
|     } | ||||
|  | ||||
|     def clean(self, value): | ||||
|         """ | ||||
|         Value can be either a string in the format XX.XXX.XXX/XXXX-XX or a | ||||
| @@ -131,10 +150,9 @@ class BRCNPJField(Field): | ||||
|         try: | ||||
|             int(value) | ||||
|         except ValueError: | ||||
|             raise ValidationError("This field requires only numbers.") | ||||
|             raise ValidationError(self.error_messages['digits_only']) | ||||
|         if len(value) != 14: | ||||
|             raise ValidationError( | ||||
|                 _("This field requires at least 14 digits")) | ||||
|             raise ValidationError(self.error_messages['max_digits']) | ||||
|         orig_dv = value[-2:] | ||||
|  | ||||
|         new_1dv = sum([i * int(value[idx]) for idx, i in enumerate(range(5, 1, -1) + range(9, 1, -1))]) | ||||
| @@ -144,7 +162,6 @@ class BRCNPJField(Field): | ||||
|         new_2dv = DV_maker(new_2dv % 11) | ||||
|         value = value[:-1] + str(new_2dv) | ||||
|         if value[-2:] != orig_dv: | ||||
|             raise ValidationError(_("Invalid CNPJ number.")) | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
|         return orig_value | ||||
|  | ||||
|   | ||||
| @@ -1,37 +1,43 @@ | ||||
| """  | ||||
| Canada-specific Form helpers  | ||||
| """  | ||||
|   | ||||
| from django.newforms import ValidationError  | ||||
| from django.newforms.fields import Field, RegexField, Select, EMPTY_VALUES  | ||||
| from django.newforms.util import smart_unicode  | ||||
| """ | ||||
| Canada-specific Form helpers | ||||
| """ | ||||
|  | ||||
| from django.newforms import ValidationError | ||||
| from django.newforms.fields import Field, RegexField, Select, EMPTY_VALUES | ||||
| from django.newforms.util import smart_unicode | ||||
| from django.utils.translation import gettext, ugettext | ||||
| import re  | ||||
|   | ||||
| import re | ||||
|  | ||||
| phone_digits_re = re.compile(r'^(?:1-?)?(\d{3})[-\.]?(\d{3})[-\.]?(\d{4})$') | ||||
| sin_re = re.compile(r"^(\d{3})-(\d{3})-(\d{3})$") | ||||
|   | ||||
| class CAPostalCodeField(RegexField):  | ||||
|     """Canadian postal code field."""  | ||||
|     def __init__(self, *args, **kwargs):  | ||||
|         super(CAPostalCodeField, self).__init__(r'^[ABCEGHJKLMNPRSTVXYZ]\d[A-Z] \d[A-Z]\d$',  | ||||
|             max_length=None, min_length=None,  | ||||
|             error_message=gettext(u'Enter a postal code in the format XXX XXX.'),  | ||||
|             *args, **kwargs)  | ||||
|   | ||||
| class CAPhoneNumberField(Field):  | ||||
|     """Canadian phone number field."""  | ||||
|     def clean(self, value):  | ||||
|         """Validate a phone number.  | ||||
|         """  | ||||
|         super(CAPhoneNumberField, self).clean(value)  | ||||
|  | ||||
| class CAPostalCodeField(RegexField): | ||||
|     """Canadian postal code field.""" | ||||
|     default_error_messages = { | ||||
|         'invalid': gettext(u'Enter a postal code in the format XXX XXX.'), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(CAPostalCodeField, self).__init__(r'^[ABCEGHJKLMNPRSTVXYZ]\d[A-Z] \d[A-Z]\d$', | ||||
|             max_length=None, min_length=None, *args, **kwargs) | ||||
|  | ||||
| class CAPhoneNumberField(Field): | ||||
|     """Canadian phone number field.""" | ||||
|     default_error_messages = { | ||||
|         'invalid': u'Phone numbers must be in XXX-XXX-XXXX format.', | ||||
|     } | ||||
|  | ||||
|     def clean(self, value): | ||||
|         """Validate a phone number. | ||||
|         """ | ||||
|         super(CAPhoneNumberField, self).clean(value) | ||||
|         if value in EMPTY_VALUES: | ||||
|             return u'' | ||||
|         value = re.sub('(\(|\)|\s+)', '', smart_unicode(value)) | ||||
|         m = phone_digits_re.search(value) | ||||
|         if m: | ||||
|             return u'%s-%s-%s' % (m.group(1), m.group(2), m.group(3)) | ||||
|         raise ValidationError(u'Phone numbers must be in XXX-XXX-XXXX format.')  | ||||
|         raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
| class CAProvinceField(Field): | ||||
|     """ | ||||
| @@ -39,6 +45,10 @@ class CAProvinceField(Field): | ||||
|     It normalizes the input to the standard two-leter postal service | ||||
|     abbreviation for the given province. | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': u'Enter a Canadian province or territory.', | ||||
|     } | ||||
|  | ||||
|     def clean(self, value): | ||||
|         from ca_provinces import PROVINCES_NORMALIZED | ||||
|         super(CAProvinceField, self).clean(value) | ||||
| @@ -53,17 +63,17 @@ class CAProvinceField(Field): | ||||
|                 return PROVINCES_NORMALIZED[value.strip().lower()].decode('ascii') | ||||
|             except KeyError: | ||||
|                 pass | ||||
|         raise ValidationError(u'Enter a Canadian province or territory.') | ||||
|   | ||||
| class CAProvinceSelect(Select):  | ||||
|     """  | ||||
|     A Select widget that uses a list of Canadian provinces and  | ||||
|     territories as its choices.  | ||||
|     """  | ||||
|     def __init__(self, attrs=None):  | ||||
|         from ca_provinces import PROVINCE_CHOICES # relative import  | ||||
|         raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
| class CAProvinceSelect(Select): | ||||
|     """ | ||||
|     A Select widget that uses a list of Canadian provinces and | ||||
|     territories as its choices. | ||||
|     """ | ||||
|     def __init__(self, attrs=None): | ||||
|         from ca_provinces import PROVINCE_CHOICES # relative import | ||||
|         super(CAProvinceSelect, self).__init__(attrs, choices=PROVINCE_CHOICES) | ||||
|              | ||||
|  | ||||
| class CASocialInsuranceNumberField(Field): | ||||
|     """ | ||||
|     A Canadian Social Insurance Number (SIN). | ||||
| @@ -74,24 +84,28 @@ class CASocialInsuranceNumberField(Field): | ||||
|         * Passes the check digit process "Luhn Algorithm" | ||||
|              See: http://en.wikipedia.org/wiki/Social_Insurance_Number | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': ugettext('Enter a valid Canadian Social Insurance number in XXX-XXX-XXXX format.'), | ||||
|     } | ||||
|  | ||||
|     def clean(self, value): | ||||
|         super(CASocialInsuranceNumberField, self).clean(value) | ||||
|         if value in EMPTY_VALUES: | ||||
|             return u'' | ||||
|         msg = ugettext('Enter a valid Canadian Social Insurance number in XXX-XXX-XXXX format.') | ||||
|  | ||||
|         match = re.match(sin_re, value) | ||||
|         if not match: | ||||
|             raise ValidationError(msg) | ||||
|              | ||||
|         number = u'%s-%s-%s' % (match.group(1), match.group(2), match.group(3))     | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
|         number = u'%s-%s-%s' % (match.group(1), match.group(2), match.group(3)) | ||||
|         check_number = u'%s%s%s' % (match.group(1), match.group(2), match.group(3)) | ||||
|         if not self.luhn_checksum_is_valid(check_number): | ||||
|             raise ValidationError(msg) | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|         return number | ||||
|          | ||||
|  | ||||
|     def luhn_checksum_is_valid(self, number): | ||||
|         """ | ||||
|         Checks to make sure that the SIN passes a luhn mod-10 checksum  | ||||
|         Checks to make sure that the SIN passes a luhn mod-10 checksum | ||||
|         See: http://en.wikipedia.org/wiki/Luhn_algorithm | ||||
|         """ | ||||
|  | ||||
| @@ -109,4 +123,4 @@ class CASocialInsuranceNumberField(Field): | ||||
|  | ||||
|             sum = sum + digit | ||||
|  | ||||
|         return ( (sum % 10) == 0 ) | ||||
|         return ( (sum % 10) == 0 ) | ||||
|   | ||||
| @@ -12,11 +12,13 @@ id_re = re.compile(r"^(?P<idnumber>\w{8})(?P<pos9>(\d{1}|<))(?P<checksum>\d{1})$ | ||||
| phone_digits_re = re.compile(r'^0([1-9]{1})\d{8}$') | ||||
|  | ||||
| class CHZipCodeField(RegexField): | ||||
|     default_error_messages = { | ||||
|         'invalid': ugettext('Enter a zip code in the format XXXX.'), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(CHZipCodeField, self).__init__(r'^\d{4}$', | ||||
|         max_length=None, min_length=None, | ||||
|         error_message=ugettext('Enter a zip code in the format XXXX.'), | ||||
|         *args, **kwargs) | ||||
|         max_length=None, min_length=None, *args, **kwargs) | ||||
|  | ||||
| class CHPhoneNumberField(Field): | ||||
|     """ | ||||
| @@ -25,6 +27,10 @@ class CHPhoneNumberField(Field): | ||||
|     '0XX.XXX.XX.XX' and '0XXXXXXXXX' validate but are corrected to | ||||
|     '0XX XXX XX XX'. | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': 'Phone numbers must be in 0XX XXX XX XX format.', | ||||
|     } | ||||
|  | ||||
|     def clean(self, value): | ||||
|         super(CHPhoneNumberField, self).clean(value) | ||||
|         if value in EMPTY_VALUES: | ||||
| @@ -33,7 +39,7 @@ class CHPhoneNumberField(Field): | ||||
|         m = phone_digits_re.search(value) | ||||
|         if m: | ||||
|             return u'%s %s %s %s' % (value[0:3], value[3:6], value[6:8], value[8:10]) | ||||
|         raise ValidationError('Phone numbers must be in 0XX XXX XX XX format.') | ||||
|         raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
| class CHStateSelect(Select): | ||||
|     """ | ||||
| @@ -54,6 +60,10 @@ class CHIdentityCardNumberField(Field): | ||||
|  | ||||
|     Algorithm is documented at http://adi.kousz.ch/artikel/IDCHE.htm | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': ugettext('Enter a valid Swiss identity or passport card number in X1234567<0 or 1234567890 format.'), | ||||
|     } | ||||
|  | ||||
|     def has_valid_checksum(self, number): | ||||
|         given_number, given_checksum = number[:-1], number[-1] | ||||
|         new_number = given_number | ||||
| @@ -87,23 +97,22 @@ class CHIdentityCardNumberField(Field): | ||||
|  | ||||
|     def clean(self, value): | ||||
|         super(CHIdentityCardNumberField, self).clean(value) | ||||
|         error_msg = ugettext('Enter a valid Swiss identity or passport card number in X1234567<0 or 1234567890 format.') | ||||
|         if value in EMPTY_VALUES: | ||||
|             return u'' | ||||
|  | ||||
|         match = re.match(id_re, value) | ||||
|         if not match: | ||||
|             raise ValidationError(error_msg) | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
|         idnumber, pos9, checksum = match.groupdict()['idnumber'], match.groupdict()['pos9'], match.groupdict()['checksum'] | ||||
|  | ||||
|         if idnumber == '00000000' or \ | ||||
|            idnumber == 'A0000000': | ||||
|             raise ValidationError(error_msg) | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
|         all_digits = "%s%s%s" % (idnumber, pos9, checksum) | ||||
|         if not self.has_valid_checksum(all_digits): | ||||
|             raise ValidationError(error_msg) | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
|         return u'%s%s%s' % (idnumber, pos9, checksum) | ||||
|  | ||||
|   | ||||
| @@ -25,16 +25,21 @@ class CLRutField(RegexField): | ||||
|     Samples for testing are available from | ||||
|     https://palena.sii.cl/cvc/dte/ee_empresas_emisoras.html | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': ugettext('Enter a valid Chilean RUT.'), | ||||
|         'strict': ugettext('Enter a valid Chilean RUT. The format is XX.XXX.XXX-X.'), | ||||
|         'checksum': ugettext('The Chilean RUT is not valid.'), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         if 'strict' in kwargs: | ||||
|             del kwargs['strict'] | ||||
|             super(CLRutField, self).__init__(r'^(\d{1,2}\.)?\d{3}\.\d{3}-[\dkK]$', | ||||
|                 error_message=ugettext('Enter valid a Chilean RUT. The format is XX.XXX.XXX-X.'), | ||||
|                         *args, **kwargs) | ||||
|                 error_message=self.default_error_messages['strict'], *args, **kwargs) | ||||
|         else: | ||||
|             # In non-strict mode, accept RUTs that validate but do not exist in | ||||
|             # the real world. | ||||
|             super(CLRutField, self).__init__(r'^[\d\.]{1,11}-?[\dkK]$', error_message=ugettext('Enter valid a Chilean RUT'), *args, **kwargs) | ||||
|             super(CLRutField, self).__init__(r'^[\d\.]{1,11}-?[\dkK]$', *args, **kwargs) | ||||
|  | ||||
|     def clean(self, value): | ||||
|         """ | ||||
| @@ -47,7 +52,7 @@ class CLRutField(RegexField): | ||||
|         if self._algorithm(rut) == verificador: | ||||
|             return self._format(rut, verificador) | ||||
|         else: | ||||
|             raise ValidationError(u'The Chilean RUT is not valid.') | ||||
|             raise ValidationError(self.error_messages['checksum']) | ||||
|  | ||||
|     def _algorithm(self, rut): | ||||
|         """ | ||||
|   | ||||
| @@ -10,11 +10,12 @@ import re | ||||
| id_re = re.compile(r"^(?P<residence>\d{10})(?P<origin>\w{1,3})[-\ ]?(?P<birthday>\d{7})[-\ ]?(?P<validity>\d{7})[-\ ]?(?P<checksum>\d{1})$") | ||||
|  | ||||
| class DEZipCodeField(RegexField): | ||||
|     default_error_messages = { | ||||
|         'invalid': ugettext('Enter a zip code in the format XXXXX.'), | ||||
|     } | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(DEZipCodeField, self).__init__(r'^\d{5}$', | ||||
|             max_length=None, min_length=None, | ||||
|             error_message=ugettext('Enter a zip code in the format XXXXX.'), | ||||
|                     *args, **kwargs) | ||||
|             max_length=None, min_length=None, *args, **kwargs) | ||||
|  | ||||
| class DEStateSelect(Select): | ||||
|     """ | ||||
| @@ -36,6 +37,10 @@ class DEIdentityCardNumberField(Field): | ||||
|  | ||||
|     Algorithm is documented at http://de.wikipedia.org/wiki/Personalausweis | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': ugettext('Enter a valid German identity card number in XXXXXXXXXXX-XXXXXXX-XXXXXXX-X format.'), | ||||
|     } | ||||
|  | ||||
|     def has_valid_checksum(self, number): | ||||
|         given_number, given_checksum = number[:-1], number[-1] | ||||
|         calculated_checksum = 0 | ||||
| @@ -57,23 +62,22 @@ class DEIdentityCardNumberField(Field): | ||||
|  | ||||
|     def clean(self, value): | ||||
|         super(DEIdentityCardNumberField, self).clean(value) | ||||
|         error_msg = ugettext('Enter a valid German identity card number in XXXXXXXXXXX-XXXXXXX-XXXXXXX-X format.') | ||||
|         if value in EMPTY_VALUES: | ||||
|             return u'' | ||||
|         match = re.match(id_re, value) | ||||
|         if not match: | ||||
|             raise ValidationError(error_msg) | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
|         gd = match.groupdict() | ||||
|         residence, origin = gd['residence'], gd['origin'] | ||||
|         birthday, validity, checksum = gd['birthday'], gd['validity'], gd['checksum'] | ||||
|  | ||||
|         if residence == '0000000000' or birthday == '0000000' or validity == '0000000': | ||||
|             raise ValidationError(error_msg) | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
|         all_digits = u"%s%s%s%s" % (residence, birthday, validity, checksum) | ||||
|         if not self.has_valid_checksum(residence) or not self.has_valid_checksum(birthday) or \ | ||||
|             not self.has_valid_checksum(validity) or not self.has_valid_checksum(all_digits): | ||||
|                 raise ValidationError(error_msg) | ||||
|                 raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
|         return u'%s%s-%s-%s-%s' % (residence, origin, birthday, validity, checksum) | ||||
|   | ||||
| @@ -15,12 +15,14 @@ class ESPostalCodeField(RegexField): | ||||
|     Spanish postal code is a five digits string, with two first digits | ||||
|     between 01 and 52, assigned to provinces code. | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': _('Enter a valid postal code in the range and format 01XXX - 52XXX.'), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(ESPostalCodeField, self).__init__( | ||||
|                 r'^(0[1-9]|[1-4][0-9]|5[0-2])\d{3}$', | ||||
|                 max_length=None, min_length=None, | ||||
|                 error_message=_('Enter a valid postal code in the range and format 01XXX - 52XXX.'), | ||||
|                 *args, **kwargs) | ||||
|                 max_length=None, min_length=None, *args, **kwargs) | ||||
|  | ||||
| class ESPhoneNumberField(RegexField): | ||||
|     """ | ||||
| @@ -33,11 +35,13 @@ class ESPhoneNumberField(RegexField): | ||||
|  | ||||
|     TODO: accept and strip characters like dot, hyphen... in phone number | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': _('Enter a valid phone number in one of the formats 6XXXXXXXX, 8XXXXXXXX or 9XXXXXXXX.'), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(ESPhoneNumberField, self).__init__(r'^(6|8|9)\d{8}$', | ||||
|                 max_length=None, min_length=None, | ||||
|                 error_message=_('Enter a valid phone number in one of the formats 6XXXXXXXX, 8XXXXXXXX or 9XXXXXXXX.'), | ||||
|                 *args, **kwargs) | ||||
|                 max_length=None, min_length=None, *args, **kwargs) | ||||
|  | ||||
| class ESIdentityCardNumberField(RegexField): | ||||
|     """ | ||||
| @@ -58,19 +62,23 @@ class ESIdentityCardNumberField(RegexField): | ||||
|     public, and different authors have different opinions on which ones allows | ||||
|     letters, so both validations are assumed true for all types. | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': _('Please enter a valid NIF, NIE, or CIF.'), | ||||
|         'invalid_only_nif': _('Please enter a valid NIF or NIE.'), | ||||
|         'invalid_nif': _('Invalid checksum for NIF.'), | ||||
|         'invalid_nie': _('Invalid checksum for NIE.'), | ||||
|         'invalid_cif': _('Invalid checksum for CIF.'), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, only_nif=False, *args, **kwargs): | ||||
|         self.only_nif = only_nif | ||||
|         self.nif_control = 'TRWAGMYFPDXBNJZSQVHLCKE' | ||||
|         self.cif_control = 'JABCDEFGHI' | ||||
|         self.cif_types = 'ABCDEFGHKLMNPQS' | ||||
|         self.nie_types = 'XT' | ||||
|         if self.only_nif: | ||||
|             self.id_types = 'NIF or NIE' | ||||
|         else: | ||||
|             self.id_types = 'NIF, NIE, or CIF' | ||||
|         super(ESIdentityCardNumberField, self).__init__(r'^([%s]?)[ -]?(\d+)[ -]?([%s]?)$' % (self.cif_types + self.nie_types + self.cif_types.lower() + self.nie_types.lower(), self.nif_control + self.nif_control.lower()), | ||||
|                 max_length=None, min_length=None, | ||||
|                 error_message=_('Please enter a valid %s.' % self.id_types), | ||||
|                 error_message=self.default_error_messages['invalid%s' % (self.only_nif and '_only_nif' or '')], | ||||
|                 *args, **kwargs) | ||||
|  | ||||
|     def clean(self, value): | ||||
| @@ -88,13 +96,13 @@ class ESIdentityCardNumberField(RegexField): | ||||
|             if letter2 == nif_get_checksum(number): | ||||
|                 return value | ||||
|             else: | ||||
|                 raise ValidationError, _('Invalid checksum for NIF.') | ||||
|                 raise ValidationError, self.error_messages['invalid_nif'] | ||||
|         elif letter1 in self.nie_types and letter2: | ||||
|             # NIE | ||||
|             if letter2 == nif_get_checksum(number): | ||||
|                 return value | ||||
|             else: | ||||
|                 raise ValidationError, _('Invalid checksum for NIE.') | ||||
|                 raise ValidationError, self.error_messages['invalid_nie'] | ||||
|         elif not self.only_nif and letter1 in self.cif_types and len(number) in [7, 8]: | ||||
|             # CIF | ||||
|             if not letter2: | ||||
| @@ -103,9 +111,9 @@ class ESIdentityCardNumberField(RegexField): | ||||
|             if letter2 in [checksum, self.cif_control[checksum]]: | ||||
|                 return value | ||||
|             else: | ||||
|                 raise ValidationError, _('Invalid checksum for CIF.') | ||||
|                 raise ValidationError, self.error_messages['invalid_cif'] | ||||
|         else: | ||||
|             raise ValidationError, _('Please enter a valid %s.' % self.id_types) | ||||
|             raise ValidationError, self.error_messages['invalid'] | ||||
|  | ||||
| class ESCCCField(RegexField): | ||||
|     """ | ||||
| @@ -130,11 +138,14 @@ class ESCCCField(RegexField): | ||||
|  | ||||
|         TODO: allow IBAN validation too | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': _('Please enter a valid bank account number in format XXXX-XXXX-XX-XXXXXXXXXX.'), | ||||
|         'checksum': _('Invalid checksum for bank account number.'), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(ESCCCField, self).__init__(r'^\d{4}[ -]?\d{4}[ -]?\d{2}[ -]?\d{10}$', | ||||
|             max_length=None, min_length=None, | ||||
|             error_message=_('Please enter a valid bank account number in format XXXX-XXXX-XX-XXXXXXXXXX.'), | ||||
|             *args, **kwargs) | ||||
|             max_length=None, min_length=None, *args, **kwargs) | ||||
|  | ||||
|     def clean(self, value): | ||||
|         super(ESCCCField, self).clean(value) | ||||
| @@ -147,7 +158,7 @@ class ESCCCField(RegexField): | ||||
|         if get_checksum('00' + entity + office) + get_checksum(account) == checksum: | ||||
|             return value | ||||
|         else: | ||||
|             raise ValidationError, _('Invalid checksum for bank account number.') | ||||
|             raise ValidationError, self.error_messages['checksum'] | ||||
|  | ||||
| class ESRegionSelect(Select): | ||||
|     """ | ||||
|   | ||||
| @@ -8,11 +8,12 @@ from django.newforms.fields import Field, RegexField, Select, EMPTY_VALUES | ||||
| from django.utils.translation import ugettext | ||||
|  | ||||
| class FIZipCodeField(RegexField): | ||||
|     default_error_messages = { | ||||
|         'invalid': ugettext('Enter a zip code in the format XXXXX.'), | ||||
|     } | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(FIZipCodeField, self).__init__(r'^\d{5}$', | ||||
|             max_length=None, min_length=None, | ||||
|             error_message=ugettext('Enter a zip code in the format XXXXX.'), | ||||
|                     *args, **kwargs) | ||||
|             max_length=None, min_length=None, *args, **kwargs) | ||||
|  | ||||
| class FIMunicipalitySelect(Select): | ||||
|     """ | ||||
| @@ -23,6 +24,10 @@ class FIMunicipalitySelect(Select): | ||||
|         super(FIMunicipalitySelect, self).__init__(attrs, choices=MUNICIPALITY_CHOICES) | ||||
|  | ||||
| class FISocialSecurityNumber(Field): | ||||
|     default_error_messages = { | ||||
|         'invalid': ugettext('Enter a valid Finnish social security number.'), | ||||
|     } | ||||
|  | ||||
|     def clean(self, value): | ||||
|         super(FISocialSecurityNumber, self).clean(value) | ||||
|         if value in EMPTY_VALUES: | ||||
| @@ -37,9 +42,9 @@ class FISocialSecurityNumber(Field): | ||||
|             (?P<serial>(\d{3})) | ||||
|             (?P<checksum>[%s])$""" % checkmarks, value, re.VERBOSE | re.IGNORECASE) | ||||
|         if not result: | ||||
|             raise ValidationError(ugettext('Enter a valid Finnish social security number.')) | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|         gd = result.groupdict() | ||||
|         checksum = int(gd['date'] + gd['serial']) | ||||
|         if checkmarks[checksum % len(checkmarks)] == gd['checksum'].upper(): | ||||
|             return u'%s' % value.upper() | ||||
|         raise ValidationError(ugettext('Enter a valid Finnish social security number.')) | ||||
|         raise ValidationError(self.error_messages['invalid']) | ||||
|   | ||||
| @@ -11,11 +11,13 @@ import re | ||||
| phone_digits_re = re.compile(r'^0\d(\s|\.)?(\d{2}(\s|\.)?){3}\d{2}$') | ||||
|  | ||||
| class FRZipCodeField(RegexField): | ||||
|     default_error_messages = { | ||||
|         'invalid': ugettext('Enter a zip code in the format XXXXX.'), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(FRZipCodeField, self).__init__(r'^\d{5}$', | ||||
|             max_length=None, min_length=None, | ||||
|             error_message=ugettext('Enter a zip code in the format XXXXX.'), | ||||
|                     *args, **kwargs) | ||||
|             max_length=None, min_length=None, *args, **kwargs) | ||||
|  | ||||
| class FRPhoneNumberField(Field): | ||||
|     """ | ||||
| @@ -24,6 +26,10 @@ class FRPhoneNumberField(Field): | ||||
|     '0X.XX.XX.XX.XX' and '0XXXXXXXXX' validate but are corrected to | ||||
|     '0X XX XX XX XX'. | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': u'Phone numbers must be in 0X XX XX XX XX format.', | ||||
|     } | ||||
|  | ||||
|     def clean(self, value): | ||||
|         super(FRPhoneNumberField, self).clean(value) | ||||
|         if value in EMPTY_VALUES: | ||||
| @@ -32,7 +38,7 @@ class FRPhoneNumberField(Field): | ||||
|         m = phone_digits_re.search(value) | ||||
|         if m: | ||||
|             return u'%s %s %s %s %s' % (value[0:2], value[2:4], value[4:6], value[6:8], value[8:10]) | ||||
|         raise ValidationError(u'Phone numbers must be in 0X XX XX XX XX format.') | ||||
|         raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
| class FRDepartmentSelect(Select): | ||||
|     """ | ||||
|   | ||||
| @@ -10,11 +10,13 @@ import re | ||||
|  | ||||
|  | ||||
| class INZipCodeField(RegexField): | ||||
|     default_error_messages = { | ||||
|         'invalid': gettext(u'Enter a zip code in the format XXXXXXX.'), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(INZipCodeField, self).__init__(r'^\d{6}$', | ||||
|             max_length=None, min_length=None, | ||||
|             error_message=gettext(u'Enter a zip code in the format XXXXXXX.'), | ||||
|             *args, **kwargs) | ||||
|             max_length=None, min_length=None, *args, **kwargs) | ||||
|  | ||||
| class INStateField(Field): | ||||
|     """ | ||||
| @@ -22,6 +24,10 @@ class INStateField(Field): | ||||
|     abbreviation. It normalizes the input to the standard two-letter vehicle | ||||
|     registration abbreviation for the given state or union territory | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': u'Enter a Indian state or territory.', | ||||
|     } | ||||
|  | ||||
|     def clean(self, value): | ||||
|         from in_states import STATES_NORMALIZED | ||||
|         super(INStateField, self).clean(value) | ||||
| @@ -36,7 +42,7 @@ class INStateField(Field): | ||||
|                 return smart_unicode(STATES_NORMALIZED[value.strip().lower()]) | ||||
|             except KeyError: | ||||
|                 pass | ||||
|         raise ValidationError(u'Enter a Indian state or territory.') | ||||
|         raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
| class INStateSelect(Select): | ||||
|     """ | ||||
|   | ||||
| @@ -13,10 +13,14 @@ class ISIdNumberField(RegexField): | ||||
|     Icelandic identification number (kennitala). This is a number every citizen | ||||
|     of Iceland has. | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': ugettext('Enter a valid Icelandic identification number. The format is XXXXXX-XXXX.'), | ||||
|         'checksum': ugettext(u'The Icelandic identification number is not valid.'), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         error_msg = ugettext('Enter a valid Icelandic identification number. The format is XXXXXX-XXXX.') | ||||
|         kwargs['min_length'],kwargs['max_length'] = 10,11 | ||||
|         super(ISIdNumberField, self).__init__(r'^\d{6}(-| )?\d{4}$', error_message=error_msg, *args, **kwargs) | ||||
|         super(ISIdNumberField, self).__init__(r'^\d{6}(-| )?\d{4}$', *args, **kwargs) | ||||
|  | ||||
|     def clean(self, value): | ||||
|         value = super(ISIdNumberField, self).clean(value) | ||||
| @@ -28,7 +32,7 @@ class ISIdNumberField(RegexField): | ||||
|         if self._validate(value): | ||||
|             return self._format(value) | ||||
|         else: | ||||
|             raise ValidationError(ugettext(u'The Icelandic identification number is not valid.')) | ||||
|             raise ValidationError(self.error_messages['checksum']) | ||||
|  | ||||
|     def _canonify(self, value): | ||||
|         """ | ||||
|   | ||||
| @@ -10,11 +10,12 @@ from django.contrib.localflavor.it.util import ssn_check_digit, vat_number_check | ||||
| import re | ||||
|  | ||||
| class ITZipCodeField(RegexField): | ||||
|     default_error_messages = { | ||||
|         'invalid': ugettext('Enter a valid zip code.'), | ||||
|     } | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(ITZipCodeField, self).__init__(r'^\d{5}$', | ||||
|         max_length=None, min_length=None, | ||||
|         error_message=ugettext('Enter a valid zip code.'), | ||||
|                 *args, **kwargs) | ||||
|         max_length=None, min_length=None, *args, **kwargs) | ||||
|  | ||||
| class ITRegionSelect(Select): | ||||
|     """ | ||||
| @@ -38,11 +39,13 @@ class ITSocialSecurityNumberField(RegexField): | ||||
|     For reference see http://www.agenziaentrate.it/ and search for | ||||
|     'Informazioni sulla codificazione delle persone fisiche'. | ||||
|     """ | ||||
|     err_msg = ugettext(u'Enter a valid Social Security number.') | ||||
|     default_error_messages = { | ||||
|         'invalid': ugettext(u'Enter a valid Social Security number.'), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(ITSocialSecurityNumberField, self).__init__(r'^\w{3}\s*\w{3}\s*\w{5}\s*\w{5}$', | ||||
|         max_length=None, min_length=None, error_message=self.err_msg, | ||||
|         *args, **kwargs) | ||||
|         max_length=None, min_length=None, *args, **kwargs) | ||||
|  | ||||
|     def clean(self, value): | ||||
|         value = super(ITSocialSecurityNumberField, self).clean(value) | ||||
| @@ -52,26 +55,29 @@ class ITSocialSecurityNumberField(RegexField): | ||||
|         try: | ||||
|             check_digit = ssn_check_digit(value) | ||||
|         except ValueError: | ||||
|             raise ValidationError(self.err_msg) | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|         if not value[15] == check_digit: | ||||
|             raise ValidationError(self.err_msg) | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|         return value | ||||
|  | ||||
| class ITVatNumberField(Field): | ||||
|     """ | ||||
|     A form field that validates Italian VAT numbers (partita IVA). | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': ugettext(u'Enter a valid VAT number.'), | ||||
|     } | ||||
|  | ||||
|     def clean(self, value): | ||||
|         value = super(ITVatNumberField, self).clean(value) | ||||
|         if value == u'': | ||||
|             return value | ||||
|         err_msg = ugettext(u'Enter a valid VAT number.') | ||||
|         try: | ||||
|             vat_number = int(value) | ||||
|         except ValueError: | ||||
|             raise ValidationError(err_msg) | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|         vat_number = str(vat_number).zfill(11) | ||||
|         check_digit = vat_number_check_digit(vat_number[0:10]) | ||||
|         if not vat_number[10] == check_digit: | ||||
|             raise ValidationError(err_msg) | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|         return smart_unicode(vat_number) | ||||
|   | ||||
| @@ -15,11 +15,13 @@ class JPPostalCodeField(RegexField): | ||||
|  | ||||
|     Accepts 7 digits, with or without a hyphen. | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': ugettext('Enter a postal code in the format XXXXXXX or XXX-XXXX.'), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(JPPostalCodeField, self).__init__(r'^\d{3}-\d{4}$|^\d{7}$', | ||||
|             max_length=None, min_length=None, | ||||
|             error_message=ugettext('Enter a postal code in the format XXXXXXX or XXX-XXXX.'), | ||||
|                     *args, **kwargs) | ||||
|             max_length=None, min_length=None, *args, **kwargs) | ||||
|  | ||||
|     def clean(self, value): | ||||
|         """ | ||||
|   | ||||
| @@ -17,24 +17,27 @@ class NLZipCodeField(Field): | ||||
|     """ | ||||
|     A Dutch postal code field. | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': _('Enter a valid postal code'), | ||||
|     } | ||||
|  | ||||
|     def clean(self, value): | ||||
|         super(NLZipCodeField, self).clean(value) | ||||
|         if value in EMPTY_VALUES: | ||||
|             return u'' | ||||
|          | ||||
|         msg = _('Enter a valid postal code') | ||||
|  | ||||
|         value = value.strip().upper().replace(' ', '') | ||||
|         if not pc_re.search(value): | ||||
|             raise ValidationError(msg) | ||||
|          | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
|         if int(value[:4]) < 1000: | ||||
|             raise ValidationError(msg) | ||||
|          | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
|         return u'%s %s' % (value[:4], value[4:]) | ||||
|  | ||||
| class NLProvinceSelect(Select): | ||||
|     """ | ||||
|     A Select widget that uses a list of provinces of the Netherlands as its  | ||||
|     A Select widget that uses a list of provinces of the Netherlands as its | ||||
|     choices. | ||||
|     """ | ||||
|     def __init__(self, attrs=None): | ||||
| @@ -45,48 +48,53 @@ class NLPhoneNumberField(Field): | ||||
|     """ | ||||
|     A Dutch telephone number field. | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': _('Enter a valid phone number'), | ||||
|     } | ||||
|  | ||||
|     def clean(self, value): | ||||
|         super(NLPhoneNumberField, self).clean(value) | ||||
|         if value in EMPTY_VALUES: | ||||
|             return u'' | ||||
|          | ||||
|         msg = _('Enter a valid phone number') | ||||
|  | ||||
|         phone_nr = re.sub('[\-\s\(\)]', '', smart_unicode(value)) | ||||
|          | ||||
|  | ||||
|         if len(phone_nr) == 10 and numeric_re.search(phone_nr): | ||||
|             return value | ||||
|          | ||||
|  | ||||
|         if phone_nr[:3] == '+31' and len(phone_nr) == 12 and \ | ||||
|            numeric_re.search(phone_nr[3:]): | ||||
|             return value | ||||
|          | ||||
|         raise ValidationError(msg) | ||||
|  | ||||
|         raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
| class NLSoFiNumberField(Field): | ||||
|     """ | ||||
|     A Dutch social security number (SoFi/BSN) field. | ||||
|   | ||||
|  | ||||
|     http://nl.wikipedia.org/wiki/Sofinummer | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': _('Enter a valid SoFi number'), | ||||
|     } | ||||
|  | ||||
|     def clean(self, value): | ||||
|         super(NLSoFiNumberField, self).clean(value) | ||||
|         if value in EMPTY_VALUES: | ||||
|             return u'' | ||||
|          | ||||
|         msg = _('Enter a valid SoFi number') | ||||
|          | ||||
|  | ||||
|         if not sofi_re.search(value): | ||||
|             raise ValidationError(msg) | ||||
|          | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
|         if int(value) == 0: | ||||
|             raise ValidationError(msg) | ||||
|          | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
|         checksum = 0 | ||||
|         for i in range(9, 1, -1): | ||||
|             checksum += int(value[9-i]) * i | ||||
|         checksum -= int(value[-1]) | ||||
|          | ||||
|  | ||||
|         if checksum % 11 != 0: | ||||
|             raise ValidationError(msg) | ||||
|          | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
|         return value | ||||
|   | ||||
| @@ -8,11 +8,13 @@ from django.newforms.fields import Field, RegexField, Select, EMPTY_VALUES | ||||
| from django.utils.translation import ugettext | ||||
|  | ||||
| class NOZipCodeField(RegexField): | ||||
|     default_error_messages = { | ||||
|         'invalid': ugettext('Enter a zip code in the format XXXX.'), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(NOZipCodeField, self).__init__(r'^\d{4}$', | ||||
|             max_length=None, min_length=None, | ||||
|             error_message=ugettext('Enter a zip code in the format XXXX.'), | ||||
|                     *args, **kwargs) | ||||
|             max_length=None, min_length=None, *args, **kwargs) | ||||
|  | ||||
| class NOMunicipalitySelect(Select): | ||||
|     """ | ||||
| @@ -27,14 +29,17 @@ class NOSocialSecurityNumber(Field): | ||||
|     """ | ||||
|     Algorithm is documented at http://no.wikipedia.org/wiki/Personnummer | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': ugettext(u'Enter a valid Norwegian social security number.'), | ||||
|     } | ||||
|  | ||||
|     def clean(self, value): | ||||
|         super(NOSocialSecurityNumber, self).clean(value) | ||||
|         if value in EMPTY_VALUES: | ||||
|             return u'' | ||||
|  | ||||
|         msg = ugettext(u'Enter a valid Norwegian social security number.') | ||||
|         if not re.match(r'^\d{11}$', value): | ||||
|             raise ValidationError(msg) | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
|         day = int(value[:2]) | ||||
|         month = int(value[2:4]) | ||||
| @@ -52,7 +57,7 @@ class NOSocialSecurityNumber(Field): | ||||
|             if 900 <= inum < 1000 and year2 > 39: | ||||
|                 self.birthday = datetime.date(1900+year2, month, day) | ||||
|         except ValueError: | ||||
|             raise ValidationError(msg) | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
|         sexnum = int(value[8]) | ||||
|         if sexnum % 2 == 0: | ||||
| @@ -68,9 +73,9 @@ class NOSocialSecurityNumber(Field): | ||||
|             return sum([(a * b) for (a, b) in zip(aval, bval)]) | ||||
|  | ||||
|         if multiply_reduce(digits, weight_1) % 11 != 0: | ||||
|             raise ValidationError(msg) | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|         if multiply_reduce(digits, weight_2) % 11 != 0: | ||||
|             raise ValidationError(msg) | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
|         return value | ||||
|  | ||||
|   | ||||
| @@ -19,6 +19,11 @@ class PEDNIField(CharField): | ||||
|     """ | ||||
|     A field that validates `Documento Nacional de IdentidadŽ (DNI) numbers. | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': ugettext("This field requires only numbers."), | ||||
|         'max_digits': ugettext("This field requires 8 digits."), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(PEDNIField, self).__init__(max_length=8, min_length=8, *args, | ||||
|                 **kwargs) | ||||
| @@ -31,9 +36,9 @@ class PEDNIField(CharField): | ||||
|         if value in EMPTY_VALUES: | ||||
|             return u'' | ||||
|         if not value.isdigit(): | ||||
|             raise ValidationError(ugettext("This field requires only numbers.")) | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|         if len(value) != 8: | ||||
|             raise ValidationError(ugettext("This field requires 8 digits.")) | ||||
|             raise ValidationError(self.error_messages['max_digits']) | ||||
|  | ||||
|         return value | ||||
|  | ||||
| @@ -42,6 +47,11 @@ class PERUCField(RegexField): | ||||
|     This field validates a RUC (Registro Unico de Contribuyentes). A RUC is of | ||||
|     the form XXXXXXXXXXX. | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': ugettext("This field requires only numbers."), | ||||
|         'max_digits': ugettext("This field requires 11 digits."), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(PERUCField, self).__init__(max_length=11, min_length=11, *args, | ||||
|             **kwargs) | ||||
| @@ -54,8 +64,8 @@ class PERUCField(RegexField): | ||||
|         if value in EMPTY_VALUES: | ||||
|             return u'' | ||||
|         if not value.isdigit(): | ||||
|             raise ValidationError(ugettext("This field requires only numbers.")) | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|         if len(value) != 11: | ||||
|             raise ValidationError(ugettext("This field requires 11 digits.")) | ||||
|             raise ValidationError(self.error_messages['max_digits']) | ||||
|         return value | ||||
|  | ||||
|   | ||||
| @@ -35,16 +35,19 @@ class PLNationalIdentificationNumberField(RegexField): | ||||
|  | ||||
|     The algorithm is documented at http://en.wikipedia.org/wiki/PESEL. | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': _(u'National Identification Number consists of 11 digits.'), | ||||
|         'checksum': _(u'Wrong checksum for the National Identification Number.'), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(PLNationalIdentificationNumberField, self).__init__(r'^\d{11}$', | ||||
|             max_length=None, min_length=None, error_message=_(u'National Identification Number consists of 11 digits.'), | ||||
|             *args, **kwargs) | ||||
|             max_length=None, min_length=None, *args, **kwargs) | ||||
|  | ||||
|     def clean(self,value): | ||||
|         super(PLNationalIdentificationNumberField, self).clean(value) | ||||
|         if not self.has_valid_checksum(value): | ||||
|             raise ValidationError(_(u'Wrong checksum for the National Identification Number.')) | ||||
|             raise ValidationError(self.error_messages['checksum']) | ||||
|         return u'%s' % value | ||||
|  | ||||
|     def has_valid_checksum(self, number): | ||||
| @@ -65,17 +68,20 @@ class PLTaxNumberField(RegexField): | ||||
|     Checksum algorithm based on documentation at | ||||
|     http://wipos.p.lodz.pl/zylla/ut/nip-rego.html | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': _(u'Enter a tax number field (NIP) in the format XXX-XXX-XX-XX or XX-XX-XXX-XXX.'), | ||||
|         'checksum': _(u'Wrong checksum for the Tax Number (NIP).'), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(PLTaxNumberField, self).__init__(r'^\d{3}-\d{3}-\d{2}-\d{2}$|^\d{2}-\d{2}-\d{3}-\d{3}$', | ||||
|             max_length=None, min_length=None, | ||||
|             error_message=_(u'Enter a tax number field (NIP) in the format XXX-XXX-XX-XX or XX-XX-XXX-XXX.'),  *args, **kwargs) | ||||
|             max_length=None, min_length=None, *args, **kwargs) | ||||
|  | ||||
|     def clean(self,value): | ||||
|         super(PLTaxNumberField, self).clean(value) | ||||
|         value = re.sub("[-]", "", value) | ||||
|         if not self.has_valid_checksum(value): | ||||
|             raise ValidationError(_(u'Wrong checksum for the Tax Number (NIP).')) | ||||
|             raise ValidationError(self.error_messages['checksum']) | ||||
|         return u'%s' % value | ||||
|  | ||||
|     def has_valid_checksum(self, number): | ||||
| @@ -102,15 +108,19 @@ class PLNationalBusinessRegisterField(RegexField): | ||||
|  | ||||
|     The checksum algorithm is documented at http://wipos.p.lodz.pl/zylla/ut/nip-rego.html | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': _(u'National Business Register Number (REGON) consists of 7 or 9 digits.'), | ||||
|         'checksum': _(u'Wrong checksum for the National Business Register Number (REGON).'), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(PLNationalBusinessRegisterField, self).__init__(r'^\d{7,9}$', | ||||
|             max_length=None, min_length=None, error_message=_(u'National Business Register Number (REGON) consists of 7 or 9 digits.'), | ||||
|             *args, **kwargs) | ||||
|             max_length=None, min_length=None, *args, **kwargs) | ||||
|  | ||||
|     def clean(self,value): | ||||
|         super(PLNationalBusinessRegisterField, self).clean(value) | ||||
|         if not self.has_valid_checksum(value): | ||||
|             raise ValidationError(_(u'Wrong checksum for the National Business Register Number (REGON).')) | ||||
|             raise ValidationError(self.error_messages['checksum']) | ||||
|         return u'%s' % value | ||||
|  | ||||
|     def has_valid_checksum(self, number): | ||||
| @@ -142,9 +152,10 @@ class PLPostalCodeField(RegexField): | ||||
|     A form field that validates as Polish postal code. | ||||
|     Valid code is XX-XXX where X is digit. | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': _(u'Enter a postal code in the format XX-XXX.'), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(PLPostalCodeField, self).__init__(r'^\d{2}-\d{3}$', | ||||
|             max_length=None, min_length=None, | ||||
|             error_message=_(u'Enter a postal code in the format XX-XXX.'), | ||||
|             *args, **kwargs) | ||||
|  | ||||
|             max_length=None, min_length=None, *args, **kwargs) | ||||
|   | ||||
| @@ -26,11 +26,13 @@ class SKPostalCodeField(RegexField): | ||||
|     A form field that validates its input as Slovak postal code. | ||||
|     Valid form is XXXXX or XXX XX, where X represents integer. | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': ugettext(u'Enter a postal code in the format XXXXX or XXX XX.'), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(SKPostalCodeField, self).__init__(r'^\d{5}$|^\d{3} \d{2}$', | ||||
|             max_length=None, min_length=None, | ||||
|             error_message=ugettext(u'Enter a postal code in the format XXXXX or XXX XX.'), | ||||
|             *args, **kwargs) | ||||
|             max_length=None, min_length=None, *args, **kwargs) | ||||
|  | ||||
|     def clean(self, value): | ||||
|         """ | ||||
|   | ||||
| @@ -12,11 +12,13 @@ class UKPostcodeField(RegexField): | ||||
|     The regular expression used is sourced from the schema for British Standard | ||||
|     BS7666 address types: http://www.govtalk.gov.uk/gdsc/schemas/bs7666-v2-0.xsd | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': ugettext(u'Enter a postcode. A space is required between the two postcode parts.'), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(UKPostcodeField, self).__init__(r'^(GIR 0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HIK-Y][0-9](|[0-9]|[ABEHMNPRVWXY]))|[0-9][A-HJKSTUW]) [0-9][ABD-HJLNP-UW-Z]{2})$', | ||||
|             max_length=None, min_length=None, | ||||
|             error_message=ugettext(u'Enter a postcode. A space is required between the two postcode parts.'), | ||||
|             *args, **kwargs) | ||||
|             max_length=None, min_length=None, *args, **kwargs) | ||||
|  | ||||
| class UKCountySelect(Select): | ||||
|     """ | ||||
|   | ||||
| @@ -12,13 +12,19 @@ phone_digits_re = re.compile(r'^(?:1-?)?(\d{3})[-\.]?(\d{3})[-\.]?(\d{4})$') | ||||
| ssn_re = re.compile(r"^(?P<area>\d{3})[-\ ]?(?P<group>\d{2})[-\ ]?(?P<serial>\d{4})$") | ||||
|  | ||||
| class USZipCodeField(RegexField): | ||||
|     default_error_messages = { | ||||
|         'invalid': ugettext('Enter a zip code in the format XXXXX or XXXXX-XXXX.'), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(USZipCodeField, self).__init__(r'^\d{5}(?:-\d{4})?$', | ||||
|             max_length=None, min_length=None, | ||||
|             error_message=ugettext('Enter a zip code in the format XXXXX or XXXXX-XXXX.'), | ||||
|                     *args, **kwargs) | ||||
|             max_length=None, min_length=None, *args, **kwargs) | ||||
|  | ||||
| class USPhoneNumberField(Field): | ||||
|     default_error_messages = { | ||||
|         'invalid': u'Phone numbers must be in XXX-XXX-XXXX format.', | ||||
|     } | ||||
|  | ||||
|     def clean(self, value): | ||||
|         super(USPhoneNumberField, self).clean(value) | ||||
|         if value in EMPTY_VALUES: | ||||
| @@ -27,7 +33,7 @@ class USPhoneNumberField(Field): | ||||
|         m = phone_digits_re.search(value) | ||||
|         if m: | ||||
|             return u'%s-%s-%s' % (m.group(1), m.group(2), m.group(3)) | ||||
|         raise ValidationError(u'Phone numbers must be in XXX-XXX-XXXX format.') | ||||
|         raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
| class USSocialSecurityNumberField(Field): | ||||
|     """ | ||||
| @@ -44,28 +50,31 @@ class USSocialSecurityNumberField(Field): | ||||
|           promotional use or distribution (e.g., the Woolworth's number or the | ||||
|           1962 promotional number). | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': ugettext('Enter a valid U.S. Social Security number in XXX-XX-XXXX format.'), | ||||
|     } | ||||
|  | ||||
|     def clean(self, value): | ||||
|         super(USSocialSecurityNumberField, self).clean(value) | ||||
|         if value in EMPTY_VALUES: | ||||
|             return u'' | ||||
|         msg = ugettext('Enter a valid U.S. Social Security number in XXX-XX-XXXX format.') | ||||
|         match = re.match(ssn_re, value) | ||||
|         if not match: | ||||
|             raise ValidationError(msg) | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|         area, group, serial = match.groupdict()['area'], match.groupdict()['group'], match.groupdict()['serial'] | ||||
|  | ||||
|         # First pass: no blocks of all zeroes. | ||||
|         if area == '000' or \ | ||||
|            group == '00' or \ | ||||
|            serial == '0000': | ||||
|             raise ValidationError(msg) | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
|         # Second pass: promotional and otherwise permanently invalid numbers. | ||||
|         if area == '666' or \ | ||||
|            (area == '987' and group == '65' and 4320 <= int(serial) <= 4329) or \ | ||||
|            value == '078-05-1120' or \ | ||||
|            value == '219-09-9999': | ||||
|             raise ValidationError(msg) | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|         return u'%s-%s-%s' % (area, group, serial) | ||||
|  | ||||
| class USStateField(Field): | ||||
| @@ -74,6 +83,10 @@ class USStateField(Field): | ||||
|     It normalizes the input to the standard two-leter postal service | ||||
|     abbreviation for the given state. | ||||
|     """ | ||||
|     default_error_messages = { | ||||
|         'invalid': u'Enter a U.S. state or territory.', | ||||
|     } | ||||
|  | ||||
|     def clean(self, value): | ||||
|         from us_states import STATES_NORMALIZED | ||||
|         super(USStateField, self).clean(value) | ||||
| @@ -88,7 +101,7 @@ class USStateField(Field): | ||||
|                 return STATES_NORMALIZED[value.strip().lower()].decode('ascii') | ||||
|             except KeyError: | ||||
|                 pass | ||||
|         raise ValidationError(u'Enter a U.S. state or territory.') | ||||
|         raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
| class USStateSelect(Select): | ||||
|     """ | ||||
|   | ||||
| @@ -16,10 +16,9 @@ class ZAIDField(Field): | ||||
|     using the Luhn checksum, and uses a simlistic (read: not entirely accurate) | ||||
|     check for the birthdate | ||||
|     """ | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(ZAIDField, self).__init__() | ||||
|         self.error_message = _(u'Enter a valid South African ID number') | ||||
|     default_error_messages = { | ||||
|         'invalid': _(u'Enter a valid South African ID number'), | ||||
|     } | ||||
|  | ||||
|     def clean(self, value): | ||||
|         # strip spaces and dashes | ||||
| @@ -31,9 +30,9 @@ class ZAIDField(Field): | ||||
|             return u'' | ||||
|  | ||||
|         match = re.match(id_re, value) | ||||
|          | ||||
|  | ||||
|         if not match: | ||||
|             raise ValidationError(self.error_message) | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
|         g = match.groupdict() | ||||
|  | ||||
| @@ -43,15 +42,18 @@ class ZAIDField(Field): | ||||
|             # There is no way to guess the century of a ZA ID number | ||||
|             d = date(int(g['yy']) + 2000, int(g['mm']), int(g['dd'])) | ||||
|         except ValueError: | ||||
|             raise ValidationError(self.error_message) | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
|         if not luhn(value): | ||||
|             raise ValidationError(self.error_message) | ||||
|             raise ValidationError(self.error_messages['invalid']) | ||||
|  | ||||
|         return value | ||||
|  | ||||
| class ZAPostCodeField(RegexField): | ||||
|     default_error_messages = { | ||||
|         'invalid': _(u'Enter a valid South African postal code'), | ||||
|     } | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(ZAPostCodeField, self).__init__(r'^\d{4}$', | ||||
|             max_length=None, min_length=None, | ||||
|             error_message=_(u'Enter a valid South African postal code')) | ||||
|             max_length=None, min_length=None) | ||||
|   | ||||
| @@ -41,7 +41,7 @@ Strict RUT usage (does not allow imposible values) | ||||
| >>> rut.clean('11-6') | ||||
| Traceback (most recent call last): | ||||
| ... | ||||
| ValidationError: [u'Enter valid a Chilean RUT. The format is XX.XXX.XXX-X.'] | ||||
| ValidationError: [u'Enter a valid Chilean RUT. The format is XX.XXX.XXX-X.'] | ||||
|  | ||||
| # valid format, bad verifier. | ||||
| >>> rut.clean('11.111.111-0') | ||||
| @@ -53,17 +53,17 @@ ValidationError: [u'The Chilean RUT is not valid.'] | ||||
| >>> rut.clean('767484100') | ||||
| Traceback (most recent call last): | ||||
| ... | ||||
| ValidationError: [u'Enter valid a Chilean RUT. The format is XX.XXX.XXX-X.'] | ||||
| ValidationError: [u'Enter a valid Chilean RUT. The format is XX.XXX.XXX-X.'] | ||||
| >>> rut.clean('78.412.790-7') | ||||
| u'78.412.790-7' | ||||
| >>> rut.clean('8.334.6043') | ||||
| Traceback (most recent call last): | ||||
| ... | ||||
| ValidationError: [u'Enter valid a Chilean RUT. The format is XX.XXX.XXX-X.'] | ||||
| ValidationError: [u'Enter a valid Chilean RUT. The format is XX.XXX.XXX-X.'] | ||||
| >>> rut.clean('76793310-K') | ||||
| Traceback (most recent call last): | ||||
| ... | ||||
| ValidationError: [u'Enter valid a Chilean RUT. The format is XX.XXX.XXX-X.'] | ||||
| ValidationError: [u'Enter a valid Chilean RUT. The format is XX.XXX.XXX-X.'] | ||||
|  | ||||
| ## CLRegionSelect ######################################################### | ||||
| >>> from django.contrib.localflavor.cl.forms import CLRegionSelect | ||||
|   | ||||
		Reference in New Issue
	
	Block a user