Fixed #9066 -- Added Czech localflavor. Thanks to Elvard for the contribution.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@9876 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
0c2a5ebe97
commit
b2a4377651
|
@ -0,0 +1,22 @@
|
|||
"""
|
||||
Czech regions, translations get from http://www.crwflags.com/fotw/Flags/cz-re.html
|
||||
"""
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
REGION_CHOICES = (
|
||||
('PR', _('Prague')),
|
||||
('CE', _('Cenral Bohemian Region')),
|
||||
('SO', _('South Bohemian Region')),
|
||||
('PI', _('Pilsen Region')),
|
||||
('CA', _('Carlsbad Region')),
|
||||
('US', _('Usti Region')),
|
||||
('LB', _('Liberec Region')),
|
||||
('HK', _('Hradec Region')),
|
||||
('PA', _('Pardubice Region')),
|
||||
('VY', _('Vysocina Region')),
|
||||
('SM', _('South Moravian Region')),
|
||||
('OL', _('Olomouc Region')),
|
||||
('ZL', _('Zlin Region')),
|
||||
('MS', _('Moravian-Silesian Region')),
|
||||
)
|
|
@ -0,0 +1,140 @@
|
|||
"""
|
||||
Czech-specific form helpers
|
||||
"""
|
||||
|
||||
from django.forms import ValidationError
|
||||
from django.forms.fields import Select, RegexField, Field, EMPTY_VALUES
|
||||
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).__init__(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 verificatin 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:
|
||||
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).__init__(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'])
|
||||
|
|
@ -44,6 +44,7 @@ Countries currently supported by :mod:`~django.contrib.localflavor` are:
|
|||
* Brazil_
|
||||
* Canada_
|
||||
* Chile_
|
||||
* Czech_
|
||||
* Finland_
|
||||
* France_
|
||||
* Germany_
|
||||
|
@ -83,6 +84,7 @@ Here's an example of how to use them::
|
|||
.. _Brazil: `Brazil (br)`_
|
||||
.. _Canada: `Canada (ca)`_
|
||||
.. _Chile: `Chile (cl)`_
|
||||
.. _Czech: `Czech (cz)`_
|
||||
.. _Finland: `Finland (fi)`_
|
||||
.. _France: `France (fr)`_
|
||||
.. _Germany: `Germany (de)`_
|
||||
|
@ -231,6 +233,27 @@ Chile (``cl``)
|
|||
A ``Select`` widget that uses a list of Chilean regions (Regiones) as its
|
||||
choices.
|
||||
|
||||
Czech (``cz``)
|
||||
==============
|
||||
|
||||
.. class:: cz.forms.CZPostalCodeField
|
||||
|
||||
A form field that validates input as a Czech postal code. Valid formats
|
||||
are XXXXX or XXX XX, where X is a digit.
|
||||
|
||||
.. class:: cz.forms.CZBirthNumberField
|
||||
|
||||
A form field that validates input as a Czech Birth Number.
|
||||
A valid number must be in format XXXXXX/XXXX (slash is optional).
|
||||
|
||||
.. class:: cz.forms.CZICNumberField
|
||||
|
||||
A form field that validates input as a Czech IC number field.
|
||||
|
||||
.. class:: cz.forms.CZRegionSelect
|
||||
|
||||
A ``Select`` widget that uses a list of Czech regions as its choices.
|
||||
|
||||
Finland (``fi``)
|
||||
================
|
||||
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Tests for the contrib/localflavor/ CZ Form Fields
|
||||
|
||||
tests = r"""
|
||||
# CZPostalCodeField #########################################################
|
||||
|
||||
>>> from django.contrib.localflavor.cz.forms import CZPostalCodeField
|
||||
>>> f = CZPostalCodeField()
|
||||
>>> f.clean('84545x')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a postal code in the format XXXXX or XXX XX.']
|
||||
>>> f.clean('91909')
|
||||
u'91909'
|
||||
>>> f.clean('917 01')
|
||||
u'91701'
|
||||
>>> f.clean('12345')
|
||||
u'12345'
|
||||
>>> f.clean('123456')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a postal code in the format XXXXX or XXX XX.']
|
||||
>>> f.clean('1234')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a postal code in the format XXXXX or XXX XX.']
|
||||
>>> f.clean('123 4')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a postal code in the format XXXXX or XXX XX.']
|
||||
|
||||
# CZRegionSelect ############################################################
|
||||
|
||||
>>> from django.contrib.localflavor.cz.forms import CZRegionSelect
|
||||
>>> w = CZRegionSelect()
|
||||
>>> w.render('regions', 'TT')
|
||||
u'<select name="regions">\n<option value="PR">Prague</option>\n<option value="CE">Cenral Bohemian Region</option>\n<option value="SO">South Bohemian Region</option>\n<option value="PI">Pilsen Region</option>\n<option value="CA">Carlsbad Region</option>\n<option value="US">Usti Region</option>\n<option value="LB">Liberec Region</option>\n<option value="HK">Hradec Region</option>\n<option value="PA">Pardubice Region</option>\n<option value="VY">Vysocina Region</option>\n<option value="SM">South Moravian Region</option>\n<option value="OL">Olomouc Region</option>\n<option value="ZL">Zlin Region</option>\n<option value="MS">Moravian-Silesian Region</option>\n</select>'
|
||||
|
||||
# CZBirthNumberField ########################################################
|
||||
|
||||
>>> from django.contrib.localflavor.cz.forms import CZBirthNumberField
|
||||
>>> f = CZBirthNumberField()
|
||||
>>> f.clean('880523/1237')
|
||||
u'880523/1237'
|
||||
>>> f.clean('8805231237')
|
||||
u'8805231237'
|
||||
>>> f.clean('880523/000')
|
||||
u'880523/000'
|
||||
>>> f.clean('880523000')
|
||||
u'880523000'
|
||||
>>> f.clean('882101/0011')
|
||||
u'882101/0011'
|
||||
>>> f.clean('880523/1237', 'm')
|
||||
u'880523/1237'
|
||||
>>> f.clean('885523/1231', 'f')
|
||||
u'885523/1231'
|
||||
>>> f.clean('123456/12')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a birth number in the format XXXXXX/XXXX or XXXXXXXXXX.']
|
||||
>>> f.clean('123456/12345')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a birth number in the format XXXXXX/XXXX or XXXXXXXXXX.']
|
||||
>>> f.clean('12345612')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a birth number in the format XXXXXX/XXXX or XXXXXXXXXX.']
|
||||
>>> f.clean('12345612345')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a birth number in the format XXXXXX/XXXX or XXXXXXXXXX.']
|
||||
>>> f.clean('881523/0000', 'm')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a valid birth number.']
|
||||
>>> f.clean('885223/0000', 'm')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a valid birth number.']
|
||||
>>> f.clean('881223/0000', 'f')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a valid birth number.']
|
||||
>>> f.clean('886523/0000', 'f')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a valid birth number.']
|
||||
>>> f.clean('880523/1239')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a valid birth number.']
|
||||
>>> f.clean('8805231239')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a valid birth number.']
|
||||
>>> f.clean('990101/0011')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a valid birth number.']
|
||||
|
||||
# CZICNumberField ########################################################
|
||||
|
||||
>>> from django.contrib.localflavor.cz.forms import CZICNumberField
|
||||
>>> f = CZICNumberField()
|
||||
>>> f.clean('12345679')
|
||||
u'12345679'
|
||||
>>> f.clean('12345601')
|
||||
u'12345601'
|
||||
>>> f.clean('12345661')
|
||||
u'12345661'
|
||||
>>> f.clean('12345610')
|
||||
u'12345610'
|
||||
>>> f.clean('1234567')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a valid IC number.']
|
||||
>>> f.clean('12345660')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a valid IC number.']
|
||||
>>> f.clean('12345600')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a valid IC number.']
|
||||
"""
|
|
@ -10,6 +10,7 @@ from localflavor.br import tests as localflavor_br_tests
|
|||
from localflavor.ca import tests as localflavor_ca_tests
|
||||
from localflavor.ch import tests as localflavor_ch_tests
|
||||
from localflavor.cl import tests as localflavor_cl_tests
|
||||
from localflavor.cz import tests as localflavor_cz_tests
|
||||
from localflavor.de import tests as localflavor_de_tests
|
||||
from localflavor.es import tests as localflavor_es_tests
|
||||
from localflavor.fi import tests as localflavor_fi_tests
|
||||
|
@ -43,6 +44,7 @@ __test__ = {
|
|||
'localflavor_ca_tests': localflavor_ca_tests,
|
||||
'localflavor_ch_tests': localflavor_ch_tests,
|
||||
'localflavor_cl_tests': localflavor_cl_tests,
|
||||
'localflavor_cz_tests': localflavor_cz_tests,
|
||||
'localflavor_de_tests': localflavor_de_tests,
|
||||
'localflavor_es_tests': localflavor_es_tests,
|
||||
'localflavor_fi_tests': localflavor_fi_tests,
|
||||
|
|
Loading…
Reference in New Issue