diff -r 000000000000 -r 0d40e90630ef web/lib/django/contrib/localflavor/za/forms.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/lib/django/contrib/localflavor/za/forms.py Wed Jan 20 00:34:04 2010 +0100 @@ -0,0 +1,59 @@ +""" +South Africa-specific Form helpers +""" + +from django.forms import ValidationError +from django.forms.fields import Field, RegexField, EMPTY_VALUES +from django.utils.checksums import luhn +from django.utils.translation import gettext as _ +import re +from datetime import date + +id_re = re.compile(r'^(?P\d\d)(?P\d\d)(?P
\d\d)(?P\d{4})(?P\d{3})') + +class ZAIDField(Field): + """A form field for South African ID numbers -- the checksum is validated + using the Luhn checksum, and uses a simlistic (read: not entirely accurate) + check for the birthdate + """ + default_error_messages = { + 'invalid': _(u'Enter a valid South African ID number'), + } + + def clean(self, value): + # strip spaces and dashes + value = value.strip().replace(' ', '').replace('-', '') + + super(ZAIDField, self).clean(value) + + if value in EMPTY_VALUES: + return u'' + + match = re.match(id_re, value) + + if not match: + raise ValidationError(self.error_messages['invalid']) + + g = match.groupdict() + + try: + # The year 2000 is conveniently a leapyear. + # This algorithm will break in xx00 years which aren't leap years + # There is no way to guess the century of a ZA ID number + d = date(int(g['yy']) + 2000, int(g['mm']), int(g['dd'])) + except ValueError: + raise ValidationError(self.error_messages['invalid']) + + if not luhn(value): + raise ValidationError(self.error_messages['invalid']) + + return value + +class ZAPostCodeField(RegexField): + default_error_messages = { + 'invalid': _(u'Enter a valid South African postal code'), + } + + def __init__(self, *args, **kwargs): + super(ZAPostCodeField, self).__init__(r'^\d{4}$', + max_length=None, min_length=None)