/django/contrib/localflavor/il/forms.py
Python | 66 lines | 43 code | 7 blank | 16 comment | 3 complexity | ef611615d1932d77906fef5632156ff5 MD5 | raw file
1""" 2Israeli-specific form helpers 3""" 4import re 5 6from django.core.exceptions import ValidationError 7from django.core.validators import EMPTY_VALUES 8from django.forms.fields import RegexField, Field, EMPTY_VALUES 9from django.utils.checksums import luhn 10from django.utils.translation import ugettext_lazy as _ 11 12# Israeli ID numbers consist of up to 8 digits followed by a checksum digit. 13# Numbers which are shorter than 8 digits are effectively left-zero-padded. 14# The checksum digit is occasionally separated from the number by a hyphen, 15# and is calculated using the luhn algorithm. 16# 17# Relevant references: 18# 19# (hebrew) http://he.wikipedia.org/wiki/%D7%9E%D7%A1%D7%A4%D7%A8_%D7%96%D7%94%D7%95%D7%AA_(%D7%99%D7%A9%D7%A8%D7%90%D7%9C) 20# (hebrew) http://he.wikipedia.org/wiki/%D7%A1%D7%A4%D7%A8%D7%AA_%D7%91%D7%99%D7%A7%D7%95%D7%A8%D7%AA 21 22id_number_re = re.compile(r'^(?P<number>\d{1,8})-?(?P<check>\d)$') 23 24class ILPostalCodeField(RegexField): 25 """ 26 A form field that validates its input as an Israeli postal code. 27 Valid form is XXXXX where X represents integer. 28 """ 29 30 default_error_messages = { 31 'invalid': _(u'Enter a postal code in the format XXXXX'), 32 } 33 34 def __init__(self, *args, **kwargs): 35 super(ILPostalCodeField, self).__init__(r'^\d{5}$', *args, **kwargs) 36 37 def clean(self, value): 38 if value not in EMPTY_VALUES: 39 value = value.replace(" ", "") 40 return super(ILPostalCodeField, self).clean(value) 41 42 43class ILIDNumberField(Field): 44 """ 45 A form field that validates its input as an Israeli identification number. 46 Valid form is per the Israeli ID specification. 47 """ 48 49 default_error_messages = { 50 'invalid': _(u'Enter a valid ID number.'), 51 } 52 53 def clean(self, value): 54 value = super(ILIDNumberField, self).clean(value) 55 56 if value in EMPTY_VALUES: 57 return u'' 58 59 match = id_number_re.match(value) 60 if not match: 61 raise ValidationError(self.error_messages['invalid']) 62 63 value = match.group('number') + match.group('check') 64 if not luhn(value): 65 raise ValidationError(self.error_messages['invalid']) 66 return value