web/lib/django/contrib/localflavor/de/forms.py
author ymh <ymh.work@gmail.com>
Wed, 02 Jun 2010 18:57:35 +0200
changeset 38 77b6da96e6f1
permissions -rw-r--r--
update django
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
38
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     1
"""
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     2
DE-specific Form helpers
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     3
"""
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     4
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     5
from django.core.validators import EMPTY_VALUES
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     6
from django.forms import ValidationError
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     7
from django.forms.fields import Field, RegexField, Select
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     8
from django.utils.translation import ugettext_lazy as _
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     9
import re
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    10
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    11
id_re = re.compile(r"^(?P<residence>\d{10})(?P<origin>\w{1,3})[-\ ]?(?P<birthday>\d{7})[-\ ]?(?P<validity>\d{7})[-\ ]?(?P<checksum>\d{1})$")
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    12
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    13
class DEZipCodeField(RegexField):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    14
    default_error_messages = {
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    15
        'invalid': _('Enter a zip code in the format XXXXX.'),
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    16
    }
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    17
    def __init__(self, *args, **kwargs):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    18
        super(DEZipCodeField, self).__init__(r'^\d{5}$',
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    19
            max_length=None, min_length=None, *args, **kwargs)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    20
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    21
class DEStateSelect(Select):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    22
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    23
    A Select widget that uses a list of DE states as its choices.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    24
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    25
    def __init__(self, attrs=None):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    26
        from de_states import STATE_CHOICES
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    27
        super(DEStateSelect, self).__init__(attrs, choices=STATE_CHOICES)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    28
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    29
class DEIdentityCardNumberField(Field):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    30
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    31
    A German identity card number.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    32
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    33
    Checks the following rules to determine whether the number is valid:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    34
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    35
        * Conforms to the XXXXXXXXXXX-XXXXXXX-XXXXXXX-X format.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    36
        * No group consists entirely of zeroes.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    37
        * Included checksums match calculated checksums
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    38
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    39
    Algorithm is documented at http://de.wikipedia.org/wiki/Personalausweis
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    40
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    41
    default_error_messages = {
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    42
        'invalid': _('Enter a valid German identity card number in XXXXXXXXXXX-XXXXXXX-XXXXXXX-X format.'),
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    43
    }
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    44
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    45
    def has_valid_checksum(self, number):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    46
        given_number, given_checksum = number[:-1], number[-1]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    47
        calculated_checksum = 0
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    48
        fragment = ""
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    49
        parameter = 7
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    50
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    51
        for i in range(len(given_number)):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    52
            fragment = str(int(given_number[i]) * parameter)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    53
            if fragment.isalnum():
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    54
                calculated_checksum += int(fragment[-1])
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    55
            if parameter == 1:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    56
                parameter = 7
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    57
            elif parameter == 3:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    58
                parameter = 1
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    59
            elif parameter ==7:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    60
                parameter = 3
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    61
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    62
        return str(calculated_checksum)[-1] == given_checksum
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    63
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    64
    def clean(self, value):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    65
        super(DEIdentityCardNumberField, self).clean(value)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    66
        if value in EMPTY_VALUES:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    67
            return u''
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    68
        match = re.match(id_re, value)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    69
        if not match:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    70
            raise ValidationError(self.error_messages['invalid'])
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    71
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    72
        gd = match.groupdict()
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    73
        residence, origin = gd['residence'], gd['origin']
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    74
        birthday, validity, checksum = gd['birthday'], gd['validity'], gd['checksum']
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    75
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    76
        if residence == '0000000000' or birthday == '0000000' or validity == '0000000':
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    77
            raise ValidationError(self.error_messages['invalid'])
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    78
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    79
        all_digits = u"%s%s%s%s" % (residence, birthday, validity, checksum)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    80
        if not self.has_valid_checksum(residence) or not self.has_valid_checksum(birthday) or \
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    81
            not self.has_valid_checksum(validity) or not self.has_valid_checksum(all_digits):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    82
                raise ValidationError(self.error_messages['invalid'])
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    83
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    84
        return u'%s%s-%s-%s-%s' % (residence, origin, birthday, validity, checksum)