/django/contrib/localflavor/cz/forms.py
https://github.com/blacktear23/django · Python · 145 lines · 83 code · 29 blank · 33 comment · 24 complexity · 1aecdf1859fda0ca0a22f40787b0d352 MD5 · raw file
- """
- Czech-specific form helpers
- """
- from django.core.validators import EMPTY_VALUES
- from django.forms import ValidationError
- from django.forms.fields import Select, RegexField, Field
- from django.utils.translation import ugettext_lazy as _
- import re
- birth_number = re.compile(r'^(?P<birth>\d{6})/?(?P<id>\d{3,4})$')
- ic_number = re.compile(r'^(?P<number>\d{7})(?P<check>\d)$')
- class CZRegionSelect(Select):
- """
- A select widget widget with list of Czech regions as choices.
- """
- def __init__(self, attrs=None):
- from cz_regions import REGION_CHOICES
- super(CZRegionSelect, self).__init__(attrs, choices=REGION_CHOICES)
- class CZPostalCodeField(RegexField):
- """
- A form field that validates its input as Czech postal code.
- Valid form is XXXXX or XXX XX, where X represents integer.
- """
- default_error_messages = {
- 'invalid': _(u'Enter a postal code in the format XXXXX or XXX XX.'),
- }
- def __init__(self, *args, **kwargs):
- super(CZPostalCodeField, self).__init__(r'^\d{5}$|^\d{3} \d{2}$',
- max_length=None, min_length=None, *args, **kwargs)
- def clean(self, value):
- """
- Validates the input and returns a string that contains only numbers.
- Returns an empty string for empty values.
- """
- v = super(CZPostalCodeField, self).clean(value)
- return v.replace(' ', '')
- class CZBirthNumberField(Field):
- """
- Czech birth number field.
- """
- default_error_messages = {
- 'invalid_format': _(u'Enter a birth number in the format XXXXXX/XXXX or XXXXXXXXXX.'),
- 'invalid_gender': _(u'Invalid optional parameter Gender, valid values are \'f\' and \'m\''),
- 'invalid': _(u'Enter a valid birth number.'),
- }
- def clean(self, value, gender=None):
- super(CZBirthNumberField, self).clean(value)
- if value in EMPTY_VALUES:
- return u''
- match = re.match(birth_number, value)
- if not match:
- raise ValidationError(self.error_messages['invalid_format'])
- birth, id = match.groupdict()['birth'], match.groupdict()['id']
- # Three digits for verification number were used until 1. january 1954
- if len(id) == 3:
- return u'%s' % value
- # Birth number is in format YYMMDD. Females have month value raised by 50.
- # In case that all possible number are already used (for given date),
- # the month field is raised by 20.
- if gender is not None:
- import warnings
- warnings.warn(
- "Support for validating the gender of a CZ Birth number has been deprecated.",
- PendingDeprecationWarning)
- if gender == 'f':
- female_const = 50
- elif gender == 'm':
- female_const = 0
- else:
- raise ValidationError(self.error_messages['invalid_gender'])
- month = int(birth[2:4]) - female_const
- if (not 1 <= month <= 12):
- if (not 1 <= (month - 20) <= 12):
- raise ValidationError(self.error_messages['invalid'])
- day = int(birth[4:6])
- if not (1 <= day <= 31):
- raise ValidationError(self.error_messages['invalid'])
- # Fourth digit has been added since 1. January 1954.
- # It is modulo of dividing birth number and verification number by 11.
- # If the modulo were 10, the last number was 0 (and therefore, the whole
- # birth number wasn't divisable by 11. These number are no longer used (since 1985)
- # and the condition 'modulo == 10' can be removed in 2085.
- modulo = int(birth + id[:3]) % 11
- if (modulo == int(id[-1])) or (modulo == 10 and id[-1] == '0'):
- return u'%s' % value
- else:
- raise ValidationError(self.error_messages['invalid'])
- class CZICNumberField(Field):
- """
- Czech IC number field.
- """
- default_error_messages = {
- 'invalid': _(u'Enter a valid IC number.'),
- }
- def clean(self, value):
- super(CZICNumberField, self).clean(value)
- if value in EMPTY_VALUES:
- return u''
- match = re.match(ic_number, value)
- if not match:
- raise ValidationError(self.error_messages['invalid'])
- number, check = match.groupdict()['number'], int(match.groupdict()['check'])
- sum = 0
- weight = 8
- for digit in number:
- sum += int(digit)*weight
- weight -= 1
- remainder = sum % 11
- # remainder is equal:
- # 0 or 10: last digit is 1
- # 1: last digit is 0
- # in other case, last digin is 11 - remainder
- if (not remainder % 10 and check == 1) or \
- (remainder == 1 and check == 0) or \
- (check == (11 - remainder)):
- return u'%s' % value
- raise ValidationError(self.error_messages['invalid'])