PageRenderTime 19ms CodeModel.GetById 2ms app.highlight 12ms RepoModel.GetById 2ms app.codeStats 0ms

/django/contrib/localflavor/kw/forms.py

https://code.google.com/p/mango-py/
Python | 63 lines | 52 code | 4 blank | 7 comment | 0 complexity | 3c3ec6542e6624a4716d1915c61b27a2 MD5 | raw file
 1"""
 2Kuwait-specific Form helpers
 3"""
 4import re
 5from datetime import date
 6
 7from django.core.validators import EMPTY_VALUES
 8from django.forms import ValidationError
 9from django.forms.fields import Field, RegexField
10from django.utils.translation import gettext as _
11
12id_re = re.compile(r'^(?P<initial>\d{1})(?P<yy>\d\d)(?P<mm>\d\d)(?P<dd>\d\d)(?P<mid>\d{4})(?P<checksum>\d{1})')
13
14class KWCivilIDNumberField(Field):
15    """
16    Kuwaiti Civil ID numbers are 12 digits, second to seventh digits
17    represents the person's birthdate.
18
19    Checks the following rules to determine the validty of the number:
20        * The number consist of 12 digits.
21        * The birthdate of the person is a valid date.
22        * The calculated checksum equals to the last digit of the Civil ID.
23    """
24    default_error_messages = {
25        'invalid': _('Enter a valid Kuwaiti Civil ID number'),
26    }
27
28    def has_valid_checksum(self, value):
29        weight = (2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2)
30        calculated_checksum = 0
31        for i in range(11):
32            calculated_checksum += int(value[i]) * weight[i]
33
34        remainder = calculated_checksum % 11
35        checkdigit = 11 - remainder
36        if checkdigit != int(value[11]):
37            return False
38        return True
39
40    def clean(self, value):
41        super(KWCivilIDNumberField, self).clean(value)
42        if value in EMPTY_VALUES:
43            return u''
44
45        if not re.match(r'^\d{12}$', value):
46            raise ValidationError(self.error_messages['invalid'])
47
48        match = re.match(id_re, value)
49
50        if not match:
51            raise ValidationError(self.error_messages['invalid'])
52
53        gd = match.groupdict()
54
55        try:
56            d = date(int(gd['yy']), int(gd['mm']), int(gd['dd']))
57        except ValueError:
58            raise ValidationError(self.error_messages['invalid'])
59
60        if not self.has_valid_checksum(value):
61            raise ValidationError(self.error_messages['invalid'])
62
63        return value