app/django/contrib/localflavor/za/forms.py
changeset 54 03e267d67478
child 323 ff1a9aa48cfd
equal deleted inserted replaced
53:57b4279d8c4e 54:03e267d67478
       
     1 """
       
     2 South Africa-specific Form helpers
       
     3 """
       
     4 
       
     5 from django.newforms import ValidationError
       
     6 from django.newforms.fields import Field, RegexField, EMPTY_VALUES
       
     7 from django.utils.checksums import luhn
       
     8 from django.utils.translation import gettext as _
       
     9 import re
       
    10 from datetime import date
       
    11 
       
    12 id_re = re.compile(r'^(?P<yy>\d\d)(?P<mm>\d\d)(?P<dd>\d\d)(?P<mid>\d{4})(?P<end>\d{3})')
       
    13 
       
    14 class ZAIDField(Field):
       
    15     """A form field for South African ID numbers -- the checksum is validated
       
    16     using the Luhn checksum, and uses a simlistic (read: not entirely accurate)
       
    17     check for the birthdate
       
    18     """
       
    19     default_error_messages = {
       
    20         'invalid': _(u'Enter a valid South African ID number'),
       
    21     }
       
    22 
       
    23     def clean(self, value):
       
    24         # strip spaces and dashes
       
    25         value = value.strip().replace(' ', '').replace('-', '')
       
    26 
       
    27         super(ZAIDField, self).clean(value)
       
    28 
       
    29         if value in EMPTY_VALUES:
       
    30             return u''
       
    31 
       
    32         match = re.match(id_re, value)
       
    33 
       
    34         if not match:
       
    35             raise ValidationError(self.error_messages['invalid'])
       
    36 
       
    37         g = match.groupdict()
       
    38 
       
    39         try:
       
    40             # The year 2000 is conveniently a leapyear.
       
    41             # This algorithm will break in xx00 years which aren't leap years
       
    42             # There is no way to guess the century of a ZA ID number
       
    43             d = date(int(g['yy']) + 2000, int(g['mm']), int(g['dd']))
       
    44         except ValueError:
       
    45             raise ValidationError(self.error_messages['invalid'])
       
    46 
       
    47         if not luhn(value):
       
    48             raise ValidationError(self.error_messages['invalid'])
       
    49 
       
    50         return value
       
    51 
       
    52 class ZAPostCodeField(RegexField):
       
    53     default_error_messages = {
       
    54         'invalid': _(u'Enter a valid South African postal code'),
       
    55     }
       
    56 
       
    57     def __init__(self, *args, **kwargs):
       
    58         super(ZAPostCodeField, self).__init__(r'^\d{4}$',
       
    59             max_length=None, min_length=None)