Source code for localflavor.lt.forms

import re
from datetime import date

from django.core.exceptions import ImproperlyConfigured, ValidationError
from django.forms.fields import CharField, RegexField, Select
from django.utils.translation import gettext_lazy as _

from .lt_choices import COUNTY_CHOICES, MUNICIPALITY_CHOICES

postalcode = re.compile(r'^(LT\s?-\s?)?(?P<code>\d{5})$', re.IGNORECASE)


[docs]class LTCountySelect(Select): """A select field with the Lithuanian counties as choices""" def __init__(self, attrs=None): super().__init__(attrs, choices=COUNTY_CHOICES)
[docs]class LTMunicipalitySelect(Select): """A select field with the Lithuanian municipalities as choices""" def __init__(self, attrs=None): super().__init__(attrs, choices=MUNICIPALITY_CHOICES)
[docs]class LTIDCodeField(RegexField): """ A form field that validates as Lithuanian ID Code. Checks: * Made of exactly 11 decimal numbers. * Checksum is correct. * ID contains valid date. """ default_error_messages = { 'invalid': _('ID Code consists of exactly 11 decimal digits.'), 'checksum': _('Wrong ID Code checksum.'), 'date': _('ID Code contains invalid date.') } def __init__(self, **kwargs): super().__init__(r'^\d{11}$', **kwargs)
[docs] def clean(self, value): value = super().clean(value) if value in self.empty_values: return value if not self.valid_date(value): raise ValidationError(self.error_messages['date'], code='date') if not self.valid_checksum(value): raise ValidationError(self.error_messages['checksum'], code='checksum') return value
def valid_checksum(self, value): first_sum = 0 second_sum = 0 for i in range(10): first_sum += int(value[i]) * (i % 9 + 1) second_sum += int(value[i]) * ((i + 2) % 9 + 1) k = first_sum % 11 if k == 10: k = second_sum % 11 k = 0 if k == 10 else k return k == int(value[-1])
[docs] def valid_date(self, value): """ Check if date in ID code is valid. We won't check for dates in future as it would become too restrictive. """ try: year = {'1': 1800, '2': 1800, '3': 1900, '4': 1900, '5': 2000, '6': 2000}[value[0]] + int(value[1:3]) date(year, int(value[3:5]), int(value[5:7])) return True except (ValueError, KeyError): return False
[docs]class LTPostalCodeField(CharField): """ A form field that validates and normalizes Lithuanian postal codes. Lithuanian postal codes in following forms accepted: * XXXXX * LT-XXXXX """ default_error_messages = { 'invalid': _('Enter a postal code in the format XXXXX or LT-XXXXX.'), }
[docs] def clean(self, value): value = super().clean(value) if value in self.empty_values: return value match = re.match(postalcode, value) if not match: raise ValidationError(self.error_messages['invalid'], code='invalid') return 'LT-' + match.group('code')