Fixed #15713 -- Added a form field for validating Polish National ID Card numbers. Thanks, xtrqt.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@16116 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
086ab44336
commit
07854d1c44
|
@ -44,7 +44,7 @@ class PLPESELField(RegexField):
|
||||||
super(PLPESELField, self).__init__(r'^\d{11}$',
|
super(PLPESELField, self).__init__(r'^\d{11}$',
|
||||||
max_length=None, min_length=None, *args, **kwargs)
|
max_length=None, min_length=None, *args, **kwargs)
|
||||||
|
|
||||||
def clean(self,value):
|
def clean(self, value):
|
||||||
super(PLPESELField, self).clean(value)
|
super(PLPESELField, self).clean(value)
|
||||||
if value in EMPTY_VALUES:
|
if value in EMPTY_VALUES:
|
||||||
return u''
|
return u''
|
||||||
|
@ -62,6 +62,60 @@ class PLPESELField(RegexField):
|
||||||
result += int(number[i]) * multiple_table[i]
|
result += int(number[i]) * multiple_table[i]
|
||||||
return result % 10 == 0
|
return result % 10 == 0
|
||||||
|
|
||||||
|
class PLNationalIDCardNumberField(RegexField):
|
||||||
|
"""
|
||||||
|
A form field that validates as Polish National ID Card Number.
|
||||||
|
|
||||||
|
Checks the following rules:
|
||||||
|
* the length consist of 3 letter and 6 digits
|
||||||
|
* has a valid checksum
|
||||||
|
|
||||||
|
The algorithm is documented at http://en.wikipedia.org/wiki/Polish_identity_card.
|
||||||
|
"""
|
||||||
|
default_error_messages = {
|
||||||
|
'invalid': _(u'National ID Card Number consists of 3 letters and 6 digits.'),
|
||||||
|
'checksum': _(u'Wrong checksum for the National ID Card Number.'),
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(PLNationalIDCardNumberField, self).__init__(r'^[A-Za-z]{3}\d{6}$',
|
||||||
|
max_length=None, min_length=None, *args, **kwargs)
|
||||||
|
|
||||||
|
def clean(self,value):
|
||||||
|
super(PLNationalIDCardNumberField, self).clean(value)
|
||||||
|
if value in EMPTY_VALUES:
|
||||||
|
return u''
|
||||||
|
|
||||||
|
value = value.upper()
|
||||||
|
|
||||||
|
if not self.has_valid_checksum(value):
|
||||||
|
raise ValidationError(self.error_messages['checksum'])
|
||||||
|
return u'%s' % value
|
||||||
|
|
||||||
|
def has_valid_checksum(self, number):
|
||||||
|
"""
|
||||||
|
Calculates a checksum with the provided algorithm.
|
||||||
|
"""
|
||||||
|
letter_dict = {'A': 10, 'B': 11, 'C': 12, 'D': 13,
|
||||||
|
'E': 14, 'F': 15, 'G': 16, 'H': 17,
|
||||||
|
'I': 18, 'J': 19, 'K': 20, 'L': 21,
|
||||||
|
'M': 22, 'N': 23, 'O': 24, 'P': 25,
|
||||||
|
'Q': 26, 'R': 27, 'S': 28, 'T': 29,
|
||||||
|
'U': 30, 'V': 31, 'W': 32, 'X': 33,
|
||||||
|
'Y': 34, 'Z': 35}
|
||||||
|
|
||||||
|
# convert letters to integer values
|
||||||
|
int_table = [(not c.isdigit()) and letter_dict[c] or int(c)
|
||||||
|
for c in number]
|
||||||
|
|
||||||
|
multiple_table = (7, 3, 1, -1, 7, 3, 1, 7, 3)
|
||||||
|
result = 0
|
||||||
|
for i in range(len(int_table)):
|
||||||
|
result += int_table[i] * multiple_table[i]
|
||||||
|
|
||||||
|
return result % 10 == 0
|
||||||
|
|
||||||
|
|
||||||
class PLNIPField(RegexField):
|
class PLNIPField(RegexField):
|
||||||
"""
|
"""
|
||||||
A form field that validates as Polish Tax Number (NIP).
|
A form field that validates as Polish Tax Number (NIP).
|
||||||
|
@ -158,3 +212,4 @@ class PLPostalCodeField(RegexField):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(PLPostalCodeField, self).__init__(r'^\d{2}-\d{3}$',
|
super(PLPostalCodeField, self).__init__(r'^\d{2}-\d{3}$',
|
||||||
max_length=None, min_length=None, *args, **kwargs)
|
max_length=None, min_length=None, *args, **kwargs)
|
||||||
|
|
||||||
|
|
|
@ -759,6 +759,17 @@ Poland (``pl``)
|
||||||
|
|
||||||
.. _PESEL: http://en.wikipedia.org/wiki/PESEL
|
.. _PESEL: http://en.wikipedia.org/wiki/PESEL
|
||||||
|
|
||||||
|
.. versionadded:: 1.4
|
||||||
|
|
||||||
|
.. class:: pl.forms.PLNationalIDCardNumberField
|
||||||
|
|
||||||
|
A form field that validates input as a Polish National ID Card number. The
|
||||||
|
valid format is AAAXXXXXX, where A is letter (A-Z), X is digit and left-most
|
||||||
|
digit is checksum digit. More information about checksum calculation algorithm
|
||||||
|
see `Polish identity card`_.
|
||||||
|
|
||||||
|
.. _`Polish identity card`: http://en.wikipedia.org/wiki/Polish_identity_card
|
||||||
|
|
||||||
.. class:: pl.forms.PLREGONField
|
.. class:: pl.forms.PLREGONField
|
||||||
|
|
||||||
A form field that validates input as a Polish National Official Business
|
A form field that validates input as a Polish National Official Business
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from django.contrib.localflavor.pl.forms import (PLProvinceSelect,
|
from django.contrib.localflavor.pl.forms import (PLProvinceSelect,
|
||||||
PLCountySelect, PLPostalCodeField, PLNIPField, PLPESELField, PLREGONField)
|
PLCountySelect, PLPostalCodeField, PLNIPField, PLPESELField, PLNationalIDCardNumberField, PLREGONField)
|
||||||
|
|
||||||
from utils import LocalFlavorTestCase
|
from utils import LocalFlavorTestCase
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ class PLLocalFlavorTests(LocalFlavorTestCase):
|
||||||
<option value="west_pomerania">West Pomerania</option>
|
<option value="west_pomerania">West Pomerania</option>
|
||||||
</select>'''
|
</select>'''
|
||||||
self.assertEqual(f.render('voivodeships', 'pomerania'), out)
|
self.assertEqual(f.render('voivodeships', 'pomerania'), out)
|
||||||
|
|
||||||
def test_PLCountrySelect(self):
|
def test_PLCountrySelect(self):
|
||||||
f = PLCountySelect()
|
f = PLCountySelect()
|
||||||
out = u'''<select name="administrativeunit">
|
out = u'''<select name="administrativeunit">
|
||||||
|
@ -408,7 +408,7 @@ class PLLocalFlavorTests(LocalFlavorTestCase):
|
||||||
<option value="walecki">wa\u0142ecki</option>
|
<option value="walecki">wa\u0142ecki</option>
|
||||||
</select>'''
|
</select>'''
|
||||||
self.assertEqual(f.render('administrativeunit', 'katowice'), out)
|
self.assertEqual(f.render('administrativeunit', 'katowice'), out)
|
||||||
|
|
||||||
def test_PLPostalCodeField(self):
|
def test_PLPostalCodeField(self):
|
||||||
error_format = [u'Enter a postal code in the format XX-XXX.']
|
error_format = [u'Enter a postal code in the format XX-XXX.']
|
||||||
valid = {
|
valid = {
|
||||||
|
@ -418,7 +418,7 @@ class PLLocalFlavorTests(LocalFlavorTestCase):
|
||||||
'43--434': error_format,
|
'43--434': error_format,
|
||||||
}
|
}
|
||||||
self.assertFieldOutput(PLPostalCodeField, valid, invalid)
|
self.assertFieldOutput(PLPostalCodeField, valid, invalid)
|
||||||
|
|
||||||
def test_PLNIPField(self):
|
def test_PLNIPField(self):
|
||||||
error_format = [u'Enter a tax number field (NIP) in the format XXX-XXX-XX-XX or XX-XX-XXX-XXX.']
|
error_format = [u'Enter a tax number field (NIP) in the format XXX-XXX-XX-XX or XX-XX-XXX-XXX.']
|
||||||
error_checksum = [u'Wrong checksum for the Tax Number (NIP).']
|
error_checksum = [u'Wrong checksum for the Tax Number (NIP).']
|
||||||
|
@ -431,7 +431,7 @@ class PLLocalFlavorTests(LocalFlavorTestCase):
|
||||||
'646-241-41-23': error_checksum,
|
'646-241-41-23': error_checksum,
|
||||||
}
|
}
|
||||||
self.assertFieldOutput(PLNIPField, valid, invalid)
|
self.assertFieldOutput(PLNIPField, valid, invalid)
|
||||||
|
|
||||||
def test_PLPESELField(self):
|
def test_PLPESELField(self):
|
||||||
error_checksum = [u'Wrong checksum for the National Identification Number.']
|
error_checksum = [u'Wrong checksum for the National Identification Number.']
|
||||||
error_format = [u'National Identification Number consists of 11 digits.']
|
error_format = [u'National Identification Number consists of 11 digits.']
|
||||||
|
@ -444,7 +444,22 @@ class PLLocalFlavorTests(LocalFlavorTestCase):
|
||||||
'800716106AA': error_format,
|
'800716106AA': error_format,
|
||||||
}
|
}
|
||||||
self.assertFieldOutput(PLPESELField, valid, invalid)
|
self.assertFieldOutput(PLPESELField, valid, invalid)
|
||||||
|
|
||||||
|
def test_PLNationalIDCardNumberField(self):
|
||||||
|
error_checksum = [u'Wrong checksum for the National ID Card Number.']
|
||||||
|
error_format = [u'National ID Card Number consists of 3 letters and 6 digits.']
|
||||||
|
valid = {
|
||||||
|
'ABC123458': 'ABC123458',
|
||||||
|
'abc123458': 'ABC123458',
|
||||||
|
}
|
||||||
|
invalid = {
|
||||||
|
'ABC123457': error_checksum,
|
||||||
|
'abc123457': error_checksum,
|
||||||
|
'a12Aaaaaa': error_format,
|
||||||
|
'AA1234443': error_format,
|
||||||
|
}
|
||||||
|
self.assertFieldOutput(PLNationalIDCardNumberField, valid, invalid)
|
||||||
|
|
||||||
def test_PLREGONField(self):
|
def test_PLREGONField(self):
|
||||||
error_checksum = [u'Wrong checksum for the National Business Register Number (REGON).']
|
error_checksum = [u'Wrong checksum for the National Business Register Number (REGON).']
|
||||||
error_format = [u'National Business Register Number (REGON) consists of 9 or 14 digits.']
|
error_format = [u'National Business Register Number (REGON) consists of 9 or 14 digits.']
|
||||||
|
@ -459,4 +474,3 @@ class PLLocalFlavorTests(LocalFlavorTestCase):
|
||||||
'590096': error_format,
|
'590096': error_format,
|
||||||
}
|
}
|
||||||
self.assertFieldOutput(PLREGONField, valid, invalid)
|
self.assertFieldOutput(PLREGONField, valid, invalid)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue