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