2 South Africa-specific Form helpers
5 from django
.core
.validators
import EMPTY_VALUES
6 from django
.forms
import ValidationError
7 from django
.forms
.fields
import Field
, RegexField
8 from django
.utils
.checksums
import luhn
9 from django
.utils
.translation
import gettext
as _
11 from datetime
import date
13 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})')
15 class ZAIDField(Field
):
16 """A form field for South African ID numbers -- the checksum is validated
17 using the Luhn checksum, and uses a simlistic (read: not entirely accurate)
18 check for the birthdate
20 default_error_messages
= {
21 'invalid': _(u
'Enter a valid South African ID number'),
24 def clean(self
, value
):
25 # strip spaces and dashes
26 value
= value
.strip().replace(' ', '').replace('-', '')
28 super(ZAIDField
, self
).clean(value
)
30 if value
in EMPTY_VALUES
:
33 match
= re
.match(id_re
, value
)
36 raise ValidationError(self
.error_messages
['invalid'])
41 # The year 2000 is conveniently a leapyear.
42 # This algorithm will break in xx00 years which aren't leap years
43 # There is no way to guess the century of a ZA ID number
44 d
= date(int(g
['yy']) + 2000, int(g
['mm']), int(g
['dd']))
46 raise ValidationError(self
.error_messages
['invalid'])
49 raise ValidationError(self
.error_messages
['invalid'])
53 class ZAPostCodeField(RegexField
):
54 default_error_messages
= {
55 'invalid': _(u
'Enter a valid South African postal code'),
58 def __init__(self
, *args
, **kwargs
):
59 super(ZAPostCodeField
, self
).__init
__(r
'^\d{4}$',
60 max_length
=None, min_length
=None)