Fixed #15856 -- Added Macedonian localflavor. Many thanks to vasiliyeah.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@16385 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
9f3d76a921
commit
050e11956f
|
@ -0,0 +1,100 @@
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
from django.core.validators import EMPTY_VALUES
|
||||||
|
from django.forms import ValidationError
|
||||||
|
from django.forms.fields import RegexField, Select
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from mk_choices import MK_MUNICIPALITIES
|
||||||
|
|
||||||
|
|
||||||
|
class MKIdentityCardNumberField(RegexField):
|
||||||
|
"""
|
||||||
|
A Macedonian ID card number. Accepts both old and new format.
|
||||||
|
"""
|
||||||
|
default_error_messages = {
|
||||||
|
'invalid': _(u'Identity card numbers must contain'
|
||||||
|
' either 4 to 7 digits or an uppercase letter and 7 digits.'),
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
kwargs['min_length'] = None
|
||||||
|
kwargs['max_length'] = 8
|
||||||
|
regex = ur'(^[A-Z]{1}\d{7}$)|(^\d{4,7}$)'
|
||||||
|
super(MKIdentityCardNumberField, self).__init__(regex, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class MKMunicipalitySelect(Select):
|
||||||
|
"""
|
||||||
|
A form ``Select`` widget that uses a list of Macedonian municipalities as
|
||||||
|
choices. The label is the name of the municipality and the value
|
||||||
|
is a 2 character code for the municipality.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, attrs=None):
|
||||||
|
super(MKMunicipalitySelect, self).__init__(attrs, choices = MK_MUNICIPALITIES)
|
||||||
|
|
||||||
|
|
||||||
|
class UMCNField(RegexField):
|
||||||
|
"""
|
||||||
|
A form field that validates input as a unique master citizen
|
||||||
|
number.
|
||||||
|
|
||||||
|
The format of the unique master citizen number has been kept the same from
|
||||||
|
Yugoslavia. It is still in use in other countries as well, it is not applicable
|
||||||
|
solely in Macedonia. For more information see:
|
||||||
|
https://secure.wikimedia.org/wikipedia/en/wiki/Unique_Master_Citizen_Number
|
||||||
|
|
||||||
|
A value will pass validation if it complies to the following rules:
|
||||||
|
|
||||||
|
* Consists of exactly 13 digits
|
||||||
|
* The first 7 digits represent a valid past date in the format DDMMYYY
|
||||||
|
* The last digit of the UMCN passes a checksum test
|
||||||
|
"""
|
||||||
|
default_error_messages = {
|
||||||
|
'invalid': _(u'This field should contain exactly 13 digits.'),
|
||||||
|
'date': _(u'The first 7 digits of the UMCN must represent a valid past date.'),
|
||||||
|
'checksum': _(u'The UMCN is not valid.'),
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
kwargs['min_length'] = None
|
||||||
|
kwargs['max_length'] = 13
|
||||||
|
super(UMCNField, self).__init__(r'^\d{13}$', *args, **kwargs)
|
||||||
|
|
||||||
|
def clean(self, value):
|
||||||
|
value = super(UMCNField, self).clean(value)
|
||||||
|
|
||||||
|
if value in EMPTY_VALUES:
|
||||||
|
return u''
|
||||||
|
|
||||||
|
if not self._validate_date_part(value):
|
||||||
|
raise ValidationError(self.error_messages['date'])
|
||||||
|
if self._validate_checksum(value):
|
||||||
|
return value
|
||||||
|
else:
|
||||||
|
raise ValidationError(self.error_messages['checksum'])
|
||||||
|
|
||||||
|
def _validate_checksum(self, value):
|
||||||
|
a,b,c,d,e,f,g,h,i,j,k,l,K = [int(digit) for digit in value]
|
||||||
|
m = 11 - (( 7*(a+g) + 6*(b+h) + 5*(c+i) + 4*(d+j) + 3*(e+k) + 2*(f+l)) % 11)
|
||||||
|
if (m >= 1 and m <= 9) and K == m:
|
||||||
|
return True
|
||||||
|
elif m == 11 and K == 0:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _validate_date_part(self, value):
|
||||||
|
daypart, monthpart, yearpart = int(value[:2]), int(value[2:4]), int(value[4:7])
|
||||||
|
if yearpart >= 800:
|
||||||
|
yearpart += 1000
|
||||||
|
else:
|
||||||
|
yearpart += 2000
|
||||||
|
try:
|
||||||
|
date = datetime.datetime(year = yearpart, month = monthpart, day = daypart).date()
|
||||||
|
except ValueError:
|
||||||
|
return False
|
||||||
|
if date >= datetime.datetime.now().date():
|
||||||
|
return False
|
||||||
|
return True
|
|
@ -0,0 +1,92 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Macedonian municipalities per the reorganization from 2004.
|
||||||
|
"""
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
MK_MUNICIPALITIES = (
|
||||||
|
('AD', _(u'Aerodrom')),
|
||||||
|
('AR', _(u'Aračinovo')),
|
||||||
|
('BR', _(u'Berovo')),
|
||||||
|
('TL', _(u'Bitola')),
|
||||||
|
('BG', _(u'Bogdanci')),
|
||||||
|
('VJ', _(u'Bogovinje')),
|
||||||
|
('BS', _(u'Bosilovo')),
|
||||||
|
('BN', _(u'Brvenica')),
|
||||||
|
('BU', _(u'Butel')),
|
||||||
|
('VA', _(u'Valandovo')),
|
||||||
|
('VL', _(u'Vasilevo')),
|
||||||
|
('VV', _(u'Vevčani')),
|
||||||
|
('VE', _(u'Veles')),
|
||||||
|
('NI', _(u'Vinica')),
|
||||||
|
('VC', _(u'Vraneštica')),
|
||||||
|
('VH', _(u'Vrapčište')),
|
||||||
|
('GB', _(u'Gazi Baba')),
|
||||||
|
('GV', _(u'Gevgelija')),
|
||||||
|
('GT', _(u'Gostivar')),
|
||||||
|
('GR', _(u'Gradsko')),
|
||||||
|
('DB', _(u'Debar')),
|
||||||
|
('DA', _(u'Debarca')),
|
||||||
|
('DL', _(u'Delčevo')),
|
||||||
|
('DK', _(u'Demir Kapija')),
|
||||||
|
('DM', _(u'Demir Hisar')),
|
||||||
|
('DE', _(u'Dolneni')),
|
||||||
|
('DR', _(u'Drugovo')),
|
||||||
|
('GP', _(u'Gjorče Petrov')),
|
||||||
|
('ZE', _(u'Želino')),
|
||||||
|
('ZA', _(u'Zajas')),
|
||||||
|
('ZK', _(u'Zelenikovo')),
|
||||||
|
('ZR', _(u'Zrnovci')),
|
||||||
|
('IL', _(u'Ilinden')),
|
||||||
|
('JG', _(u'Jegunovce')),
|
||||||
|
('AV', _(u'Kavadarci')),
|
||||||
|
('KB', _(u'Karbinci')),
|
||||||
|
('KX', _(u'Karpoš')),
|
||||||
|
('VD', _(u'Kisela Voda')),
|
||||||
|
('KH', _(u'Kičevo')),
|
||||||
|
('KN', _(u'Konče')),
|
||||||
|
('OC', _(u'Koćani')),
|
||||||
|
('KY', _(u'Kratovo')),
|
||||||
|
('KZ', _(u'Kriva Palanka')),
|
||||||
|
('KG', _(u'Krivogaštani')),
|
||||||
|
('KS', _(u'Kruševo')),
|
||||||
|
('UM', _(u'Kumanovo')),
|
||||||
|
('LI', _(u'Lipkovo')),
|
||||||
|
('LO', _(u'Lozovo')),
|
||||||
|
('MR', _(u'Mavrovo i Rostuša')),
|
||||||
|
('MK', _(u'Makedonska Kamenica')),
|
||||||
|
('MD', _(u'Makedonski Brod')),
|
||||||
|
('MG', _(u'Mogila')),
|
||||||
|
('NG', _(u'Negotino')),
|
||||||
|
('NV', _(u'Novaci')),
|
||||||
|
('NS', _(u'Novo Selo')),
|
||||||
|
('OS', _(u'Oslomej')),
|
||||||
|
('OD', _(u'Ohrid')),
|
||||||
|
('PE', _(u'Petrovec')),
|
||||||
|
('PH', _(u'Pehčevo')),
|
||||||
|
('PN', _(u'Plasnica')),
|
||||||
|
('PP', _(u'Prilep')),
|
||||||
|
('PT', _(u'Probištip')),
|
||||||
|
('RV', _(u'Radoviš')),
|
||||||
|
('RN', _(u'Rankovce')),
|
||||||
|
('RE', _(u'Resen')),
|
||||||
|
('RO', _(u'Rosoman')),
|
||||||
|
('AJ', _(u'Saraj')),
|
||||||
|
('SL', _(u'Sveti Nikole')),
|
||||||
|
('SS', _(u'Sopište')),
|
||||||
|
('SD', _(u'Star Dojran')),
|
||||||
|
('NA', _(u'Staro Nagoričane')),
|
||||||
|
('UG', _(u'Struga')),
|
||||||
|
('RU', _(u'Strumica')),
|
||||||
|
('SU', _(u'Studeničani')),
|
||||||
|
('TR', _(u'Tearce')),
|
||||||
|
('ET', _(u'Tetovo')),
|
||||||
|
('CE', _(u'Centar')),
|
||||||
|
('CZ', _(u'Centar-Župa')),
|
||||||
|
('CI', _(u'Čair')),
|
||||||
|
('CA', _(u'Čaška')),
|
||||||
|
('CH', _(u'Češinovo-Obleševo')),
|
||||||
|
('CS', _(u'Čučer-Sandevo')),
|
||||||
|
('ST', _(u'Štip')),
|
||||||
|
('SO', _(u'Šuto Orizari')),
|
||||||
|
)
|
|
@ -0,0 +1,44 @@
|
||||||
|
from django.db.models.fields import CharField
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from django.contrib.localflavor.mk.mk_choices import MK_MUNICIPALITIES
|
||||||
|
from django.contrib.localflavor.mk.forms import (UMCNField as UMCNFormField,
|
||||||
|
MKIdentityCardNumberField as MKIdentityCardNumberFormField)
|
||||||
|
|
||||||
|
|
||||||
|
class MKIdentityCardNumberField(CharField):
|
||||||
|
|
||||||
|
description = _("Macedonian identity card number")
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
kwargs['max_length'] = 8
|
||||||
|
super(MKIdentityCardNumberField, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def formfield(self, **kwargs):
|
||||||
|
defaults = {'form_class' : MKIdentityCardNumberFormField}
|
||||||
|
defaults.update(kwargs)
|
||||||
|
return super(MKIdentityCardNumberField, self).formfield(**defaults)
|
||||||
|
|
||||||
|
|
||||||
|
class MKMunicipalityField(CharField):
|
||||||
|
|
||||||
|
description = _("A Macedonian municipality (2 character code)")
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
kwargs['choices'] = MK_MUNICIPALITIES
|
||||||
|
kwargs['max_length'] = 2
|
||||||
|
super(MKMunicipalityField, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class UMCNField(CharField):
|
||||||
|
|
||||||
|
description = _("Unique master citizen number (13 digits)")
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
kwargs['max_length'] = 13
|
||||||
|
super(UMCNField, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def formfield(self, **kwargs):
|
||||||
|
defaults = {'form_class' : UMCNFormField}
|
||||||
|
defaults.update(kwargs)
|
||||||
|
return super(UMCNField, self).formfield(**defaults)
|
|
@ -57,6 +57,7 @@ Countries currently supported by :mod:`~django.contrib.localflavor` are:
|
||||||
* Italy_
|
* Italy_
|
||||||
* Japan_
|
* Japan_
|
||||||
* Kuwait_
|
* Kuwait_
|
||||||
|
* Macedonia_
|
||||||
* Mexico_
|
* Mexico_
|
||||||
* `The Netherlands`_
|
* `The Netherlands`_
|
||||||
* Norway_
|
* Norway_
|
||||||
|
@ -110,6 +111,7 @@ Here's an example of how to use them::
|
||||||
.. _Italy: `Italy (it)`_
|
.. _Italy: `Italy (it)`_
|
||||||
.. _Japan: `Japan (jp)`_
|
.. _Japan: `Japan (jp)`_
|
||||||
.. _Kuwait: `Kuwait (kw)`_
|
.. _Kuwait: `Kuwait (kw)`_
|
||||||
|
.. _Macedonia: `Macedonia (mk)`_
|
||||||
.. _Mexico: `Mexico (mx)`_
|
.. _Mexico: `Mexico (mx)`_
|
||||||
.. _Norway: `Norway (no)`_
|
.. _Norway: `Norway (no)`_
|
||||||
.. _Peru: `Peru (pe)`_
|
.. _Peru: `Peru (pe)`_
|
||||||
|
@ -652,8 +654,6 @@ Israel (``il``)
|
||||||
.. _Israeli identification number: http://he.wikipedia.org/wiki/%D7%9E%D7%A1%D7%A4%D7%A8_%D7%96%D7%94%D7%95%D7%AA_(%D7%99%D7%A9%D7%A8%D7%90%D7%9C)
|
.. _Israeli identification number: http://he.wikipedia.org/wiki/%D7%9E%D7%A1%D7%A4%D7%A8_%D7%96%D7%94%D7%95%D7%AA_(%D7%99%D7%A9%D7%A8%D7%90%D7%9C)
|
||||||
.. _Luhn algorithm: http://en.wikipedia.org/wiki/Luhn_algorithm
|
.. _Luhn algorithm: http://en.wikipedia.org/wiki/Luhn_algorithm
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Italy (``it``)
|
Italy (``it``)
|
||||||
==============
|
==============
|
||||||
|
|
||||||
|
@ -705,6 +705,57 @@ Kuwait (``kw``)
|
||||||
* The birthdate of the person is a valid date.
|
* The birthdate of the person is a valid date.
|
||||||
* The calculated checksum equals to the last digit of the Civil ID.
|
* The calculated checksum equals to the last digit of the Civil ID.
|
||||||
|
|
||||||
|
Macedonia (``mk``)
|
||||||
|
===================
|
||||||
|
|
||||||
|
.. versionadded:: 1.4
|
||||||
|
|
||||||
|
.. class:: mk.forms.MKIdentityCardNumberField
|
||||||
|
|
||||||
|
A form field that validates input as a Macedonian identity card number.
|
||||||
|
Both old and new identity card numbers are supported.
|
||||||
|
|
||||||
|
|
||||||
|
.. class:: mk.forms.MKMunicipalitySelect
|
||||||
|
|
||||||
|
A form ``Select`` widget that uses a list of Macedonian municipalities as
|
||||||
|
choices.
|
||||||
|
|
||||||
|
|
||||||
|
.. class:: mk.forms.UMCNField
|
||||||
|
|
||||||
|
A form field that validates input as a unique master citizen
|
||||||
|
number.
|
||||||
|
|
||||||
|
The format of the unique master citizen number is not unique
|
||||||
|
to Macedonia. For more information see:
|
||||||
|
https://secure.wikimedia.org/wikipedia/en/wiki/Unique_Master_Citizen_Number
|
||||||
|
|
||||||
|
A value will pass validation if it complies to the following rules:
|
||||||
|
|
||||||
|
* Consists of exactly 13 digits
|
||||||
|
* The first 7 digits represent a valid past date in the format DDMMYYY
|
||||||
|
* The last digit of the UMCN passes a checksum test
|
||||||
|
|
||||||
|
|
||||||
|
.. class:: mk.models.MKIdentityCardNumberField
|
||||||
|
|
||||||
|
A model field that forms represent as a
|
||||||
|
``forms.MKIdentityCardNumberField`` field.
|
||||||
|
|
||||||
|
|
||||||
|
.. class:: mk.models.MKMunicipalityField
|
||||||
|
|
||||||
|
A model field that forms represent as a
|
||||||
|
``forms.MKMunicipalitySelect`` and stores the 2 character code of the
|
||||||
|
municipality in the database.
|
||||||
|
|
||||||
|
|
||||||
|
.. class:: mk.models.UMCNField
|
||||||
|
|
||||||
|
A model field that forms represent as a ``forms.UMCNField`` field.
|
||||||
|
|
||||||
|
|
||||||
Mexico (``mx``)
|
Mexico (``mx``)
|
||||||
===============
|
===============
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,131 @@
|
||||||
|
from django.contrib.localflavor.mk.forms import (
|
||||||
|
MKIdentityCardNumberField, MKMunicipalitySelect, UMCNField)
|
||||||
|
|
||||||
|
from utils import LocalFlavorTestCase
|
||||||
|
|
||||||
|
|
||||||
|
class MKLocalFlavorTests(LocalFlavorTestCase):
|
||||||
|
|
||||||
|
def test_MKIdentityCardNumberField(self):
|
||||||
|
error_invalid = (u'Identity card numbers must contain'
|
||||||
|
' either 4 to 7 digits or an uppercase letter and 7 digits.')
|
||||||
|
valid = {
|
||||||
|
'L0018077':'L0018077',
|
||||||
|
'A0078315' : 'A0078315',
|
||||||
|
}
|
||||||
|
invalid = {
|
||||||
|
'123': error_invalid,
|
||||||
|
'abcdf': error_invalid,
|
||||||
|
'234390a': error_invalid,
|
||||||
|
}
|
||||||
|
self.assertFieldOutput(MKIdentityCardNumberField, valid, invalid)
|
||||||
|
|
||||||
|
def test_MKMunicipalitySelect(self):
|
||||||
|
f = MKMunicipalitySelect()
|
||||||
|
out=u'''<select name="municipality">
|
||||||
|
<option value="AD">Aerodrom</option>
|
||||||
|
<option value="AR">Ara\u010dinovo</option>
|
||||||
|
<option value="BR">Berovo</option>
|
||||||
|
<option value="TL">Bitola</option>
|
||||||
|
<option value="BG">Bogdanci</option>
|
||||||
|
<option value="VJ">Bogovinje</option>
|
||||||
|
<option value="BS">Bosilovo</option>
|
||||||
|
<option value="BN">Brvenica</option>
|
||||||
|
<option value="BU">Butel</option>
|
||||||
|
<option value="VA">Valandovo</option>
|
||||||
|
<option value="VL">Vasilevo</option>
|
||||||
|
<option value="VV">Vev\u010dani</option>
|
||||||
|
<option value="VE">Veles</option>
|
||||||
|
<option value="NI">Vinica</option>
|
||||||
|
<option value="VC">Vrane\u0161tica</option>
|
||||||
|
<option value="VH">Vrap\u010di\u0161te</option>
|
||||||
|
<option value="GB">Gazi Baba</option>
|
||||||
|
<option value="GV">Gevgelija</option>
|
||||||
|
<option value="GT">Gostivar</option>
|
||||||
|
<option value="GR">Gradsko</option>
|
||||||
|
<option value="DB">Debar</option>
|
||||||
|
<option value="DA">Debarca</option>
|
||||||
|
<option value="DL" selected="selected">Del\u010devo</option>
|
||||||
|
<option value="DK">Demir Kapija</option>
|
||||||
|
<option value="DM">Demir Hisar</option>
|
||||||
|
<option value="DE">Dolneni</option>
|
||||||
|
<option value="DR">Drugovo</option>
|
||||||
|
<option value="GP">Gjor\u010de Petrov</option>
|
||||||
|
<option value="ZE">\u017delino</option>
|
||||||
|
<option value="ZA">Zajas</option>
|
||||||
|
<option value="ZK">Zelenikovo</option>
|
||||||
|
<option value="ZR">Zrnovci</option>
|
||||||
|
<option value="IL">Ilinden</option>
|
||||||
|
<option value="JG">Jegunovce</option>
|
||||||
|
<option value="AV">Kavadarci</option>
|
||||||
|
<option value="KB">Karbinci</option>
|
||||||
|
<option value="KX">Karpo\u0161</option>
|
||||||
|
<option value="VD">Kisela Voda</option>
|
||||||
|
<option value="KH">Ki\u010devo</option>
|
||||||
|
<option value="KN">Kon\u010de</option>
|
||||||
|
<option value="OC">Ko\u0107ani</option>
|
||||||
|
<option value="KY">Kratovo</option>
|
||||||
|
<option value="KZ">Kriva Palanka</option>
|
||||||
|
<option value="KG">Krivoga\u0161tani</option>
|
||||||
|
<option value="KS">Kru\u0161evo</option>
|
||||||
|
<option value="UM">Kumanovo</option>
|
||||||
|
<option value="LI">Lipkovo</option>
|
||||||
|
<option value="LO">Lozovo</option>
|
||||||
|
<option value="MR">Mavrovo i Rostu\u0161a</option>
|
||||||
|
<option value="MK">Makedonska Kamenica</option>
|
||||||
|
<option value="MD">Makedonski Brod</option>
|
||||||
|
<option value="MG">Mogila</option>
|
||||||
|
<option value="NG">Negotino</option>
|
||||||
|
<option value="NV">Novaci</option>
|
||||||
|
<option value="NS">Novo Selo</option>
|
||||||
|
<option value="OS">Oslomej</option>
|
||||||
|
<option value="OD">Ohrid</option>
|
||||||
|
<option value="PE">Petrovec</option>
|
||||||
|
<option value="PH">Peh\u010devo</option>
|
||||||
|
<option value="PN">Plasnica</option>
|
||||||
|
<option value="PP">Prilep</option>
|
||||||
|
<option value="PT">Probi\u0161tip</option>
|
||||||
|
<option value="RV">Radovi\u0161</option>
|
||||||
|
<option value="RN">Rankovce</option>
|
||||||
|
<option value="RE">Resen</option>
|
||||||
|
<option value="RO">Rosoman</option>
|
||||||
|
<option value="AJ">Saraj</option>
|
||||||
|
<option value="SL">Sveti Nikole</option>
|
||||||
|
<option value="SS">Sopi\u0161te</option>
|
||||||
|
<option value="SD">Star Dojran</option>
|
||||||
|
<option value="NA">Staro Nagori\u010dane</option>
|
||||||
|
<option value="UG">Struga</option>
|
||||||
|
<option value="RU">Strumica</option>
|
||||||
|
<option value="SU">Studeni\u010dani</option>
|
||||||
|
<option value="TR">Tearce</option>
|
||||||
|
<option value="ET">Tetovo</option>
|
||||||
|
<option value="CE">Centar</option>
|
||||||
|
<option value="CZ">Centar-\u017dupa</option>
|
||||||
|
<option value="CI">\u010cair</option>
|
||||||
|
<option value="CA">\u010ca\u0161ka</option>
|
||||||
|
<option value="CH">\u010ce\u0161inovo-Oble\u0161evo</option>
|
||||||
|
<option value="CS">\u010cu\u010der-Sandevo</option>
|
||||||
|
<option value="ST">\u0160tip</option>
|
||||||
|
<option value="SO">\u0160uto Orizari</option>
|
||||||
|
</select>'''
|
||||||
|
self.assertEqual(f.render('municipality', 'DL' ), out)
|
||||||
|
|
||||||
|
def test_UMCNField(self):
|
||||||
|
error_invalid = [u'This field should contain exactly 13 digits.']
|
||||||
|
error_checksum = [u'The UMCN is not valid.']
|
||||||
|
error_date = [u'The first 7 digits of the UMCN '
|
||||||
|
'must represent a valid past date.']
|
||||||
|
valid = {
|
||||||
|
'2402983450006': '2402983450006',
|
||||||
|
'2803984430038': '2803984430038',
|
||||||
|
'1909982045004': '1909982045004',
|
||||||
|
}
|
||||||
|
invalid = {
|
||||||
|
'240298345': error_invalid,
|
||||||
|
'abcdefghj': error_invalid,
|
||||||
|
'2402082450006': error_date,
|
||||||
|
'3002982450006': error_date,
|
||||||
|
'2402983450007': error_checksum,
|
||||||
|
'2402982450006': error_checksum,
|
||||||
|
}
|
||||||
|
self.assertFieldOutput(UMCNField, valid, invalid)
|
|
@ -23,6 +23,7 @@ from localflavor.is_ import ISLocalFlavorTests
|
||||||
from localflavor.it import ITLocalFlavorTests
|
from localflavor.it import ITLocalFlavorTests
|
||||||
from localflavor.jp import JPLocalFlavorTests
|
from localflavor.jp import JPLocalFlavorTests
|
||||||
from localflavor.kw import KWLocalFlavorTests
|
from localflavor.kw import KWLocalFlavorTests
|
||||||
|
from localflavor.mk import MKLocalFlavorTests
|
||||||
from localflavor.nl import NLLocalFlavorTests
|
from localflavor.nl import NLLocalFlavorTests
|
||||||
from localflavor.pl import PLLocalFlavorTests
|
from localflavor.pl import PLLocalFlavorTests
|
||||||
from localflavor.pt import PTLocalFlavorTests
|
from localflavor.pt import PTLocalFlavorTests
|
||||||
|
|
|
@ -36,6 +36,7 @@ from regressiontests.forms.localflavortests import (
|
||||||
ITLocalFlavorTests,
|
ITLocalFlavorTests,
|
||||||
JPLocalFlavorTests,
|
JPLocalFlavorTests,
|
||||||
KWLocalFlavorTests,
|
KWLocalFlavorTests,
|
||||||
|
MKLocalFlavorTests,
|
||||||
NLLocalFlavorTests,
|
NLLocalFlavorTests,
|
||||||
PLLocalFlavorTests,
|
PLLocalFlavorTests,
|
||||||
PTLocalFlavorTests,
|
PTLocalFlavorTests,
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
from django.forms import ModelForm
|
||||||
|
from models import MKPerson
|
||||||
|
|
||||||
|
class MKPersonForm(ModelForm):
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = MKPerson
|
|
@ -0,0 +1,14 @@
|
||||||
|
from django.db import models
|
||||||
|
from django.contrib.localflavor.mk.models import (
|
||||||
|
MKIdentityCardNumberField, MKMunicipalityField, UMCNField)
|
||||||
|
|
||||||
|
class MKPerson(models.Model):
|
||||||
|
first_name = models.CharField(max_length = 20)
|
||||||
|
last_name = models.CharField(max_length = 20)
|
||||||
|
umcn = UMCNField()
|
||||||
|
id_number = MKIdentityCardNumberField()
|
||||||
|
municipality = MKMunicipalityField(blank = True)
|
||||||
|
municipality_req = MKMunicipalityField(blank = False)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
app_label = 'localflavor'
|
|
@ -0,0 +1,176 @@
|
||||||
|
from django.test import TestCase
|
||||||
|
from forms import MKPersonForm
|
||||||
|
|
||||||
|
class MKLocalflavorTests(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.form = MKPersonForm({
|
||||||
|
'first_name':'Someone',
|
||||||
|
'last_name':'Something',
|
||||||
|
'umcn': '2402983450006',
|
||||||
|
'municipality':'OD',
|
||||||
|
'municipality_req':'VE',
|
||||||
|
'id_number':'A1234567',
|
||||||
|
})
|
||||||
|
|
||||||
|
def test_get_display_methods(self):
|
||||||
|
"""
|
||||||
|
Test that the get_*_display() methods are added to the model instances.
|
||||||
|
"""
|
||||||
|
person = self.form.save()
|
||||||
|
self.assertEqual(person.get_municipality_display(), 'Ohrid')
|
||||||
|
self.assertEqual(person.get_municipality_req_display(), 'Veles')
|
||||||
|
|
||||||
|
def test_municipality_required(self):
|
||||||
|
"""
|
||||||
|
Test that required MKMunicipalityFields throw appropriate errors.
|
||||||
|
"""
|
||||||
|
|
||||||
|
form = MKPersonForm({
|
||||||
|
'first_name':'Someone',
|
||||||
|
'last_name':'Something',
|
||||||
|
'umcn': '2402983450006',
|
||||||
|
'municipality':'OD',
|
||||||
|
'id_number':'A1234567',
|
||||||
|
})
|
||||||
|
self.assertFalse(form.is_valid())
|
||||||
|
self.assertEqual(
|
||||||
|
form.errors['municipality_req'], [u'This field is required.'])
|
||||||
|
|
||||||
|
def test_umcn_invalid(self):
|
||||||
|
"""
|
||||||
|
Test that UMCNFields throw appropriate errors for invalid UMCNs.
|
||||||
|
"""
|
||||||
|
form = MKPersonForm({
|
||||||
|
'first_name':'Someone',
|
||||||
|
'last_name':'Something',
|
||||||
|
'umcn': '2402983450007',
|
||||||
|
'municipality':'OD',
|
||||||
|
'municipality_req':'VE',
|
||||||
|
'id_number':'A1234567',
|
||||||
|
})
|
||||||
|
self.assertFalse(form.is_valid())
|
||||||
|
self.assertEqual(form.errors['umcn'], [u'The UMCN is not valid.'])
|
||||||
|
|
||||||
|
form = MKPersonForm({
|
||||||
|
'first_name':'Someone',
|
||||||
|
'last_name':'Something',
|
||||||
|
'umcn': '3002983450007',
|
||||||
|
'municipality':'OD',
|
||||||
|
'municipality_req':'VE',
|
||||||
|
'id_number':'A1234567',
|
||||||
|
})
|
||||||
|
self.assertEqual(form.errors['umcn'],
|
||||||
|
[u'The first 7 digits of the UMCN must represent a valid past date.'])
|
||||||
|
|
||||||
|
def test_idnumber_invalid(self):
|
||||||
|
"""
|
||||||
|
Test that MKIdentityCardNumberFields throw
|
||||||
|
appropriate errors for invalid values
|
||||||
|
"""
|
||||||
|
|
||||||
|
form = MKPersonForm({
|
||||||
|
'first_name':'Someone',
|
||||||
|
'last_name':'Something',
|
||||||
|
'umcn': '2402983450007',
|
||||||
|
'municipality':'OD',
|
||||||
|
'municipality_req':'VE',
|
||||||
|
'id_number':'A123456a',
|
||||||
|
})
|
||||||
|
self.assertFalse(form.is_valid())
|
||||||
|
self.assertEqual(form.errors['id_number'],
|
||||||
|
[u'Identity card numbers must contain either 4 to 7 '
|
||||||
|
'digits or an uppercase letter and 7 digits.'])
|
||||||
|
|
||||||
|
def test_field_blank_option(self):
|
||||||
|
"""
|
||||||
|
Test that the empty option is there.
|
||||||
|
"""
|
||||||
|
municipality_select_html = """\
|
||||||
|
<select name="municipality" id="id_municipality">
|
||||||
|
<option value="">---------</option>
|
||||||
|
<option value="AD">Aerodrom</option>
|
||||||
|
<option value="AR">Ara\xc4\x8dinovo</option>
|
||||||
|
<option value="BR">Berovo</option>
|
||||||
|
<option value="TL">Bitola</option>
|
||||||
|
<option value="BG">Bogdanci</option>
|
||||||
|
<option value="VJ">Bogovinje</option>
|
||||||
|
<option value="BS">Bosilovo</option>
|
||||||
|
<option value="BN">Brvenica</option>
|
||||||
|
<option value="BU">Butel</option>
|
||||||
|
<option value="VA">Valandovo</option>
|
||||||
|
<option value="VL">Vasilevo</option>
|
||||||
|
<option value="VV">Vev\xc4\x8dani</option>
|
||||||
|
<option value="VE">Veles</option>
|
||||||
|
<option value="NI">Vinica</option>
|
||||||
|
<option value="VC">Vrane\xc5\xa1tica</option>
|
||||||
|
<option value="VH">Vrap\xc4\x8di\xc5\xa1te</option>
|
||||||
|
<option value="GB">Gazi Baba</option>
|
||||||
|
<option value="GV">Gevgelija</option>
|
||||||
|
<option value="GT">Gostivar</option>
|
||||||
|
<option value="GR">Gradsko</option>
|
||||||
|
<option value="DB">Debar</option>
|
||||||
|
<option value="DA">Debarca</option>
|
||||||
|
<option value="DL">Del\xc4\x8devo</option>
|
||||||
|
<option value="DK">Demir Kapija</option>
|
||||||
|
<option value="DM">Demir Hisar</option>
|
||||||
|
<option value="DE">Dolneni</option>
|
||||||
|
<option value="DR">Drugovo</option>
|
||||||
|
<option value="GP">Gjor\xc4\x8de Petrov</option>
|
||||||
|
<option value="ZE">\xc5\xbdelino</option>
|
||||||
|
<option value="ZA">Zajas</option>
|
||||||
|
<option value="ZK">Zelenikovo</option>
|
||||||
|
<option value="ZR">Zrnovci</option>
|
||||||
|
<option value="IL">Ilinden</option>
|
||||||
|
<option value="JG">Jegunovce</option>
|
||||||
|
<option value="AV">Kavadarci</option>
|
||||||
|
<option value="KB">Karbinci</option>
|
||||||
|
<option value="KX">Karpo\xc5\xa1</option>
|
||||||
|
<option value="VD">Kisela Voda</option>
|
||||||
|
<option value="KH">Ki\xc4\x8devo</option>
|
||||||
|
<option value="KN">Kon\xc4\x8de</option>
|
||||||
|
<option value="OC">Ko\xc4\x87ani</option>
|
||||||
|
<option value="KY">Kratovo</option>
|
||||||
|
<option value="KZ">Kriva Palanka</option>
|
||||||
|
<option value="KG">Krivoga\xc5\xa1tani</option>
|
||||||
|
<option value="KS">Kru\xc5\xa1evo</option>
|
||||||
|
<option value="UM">Kumanovo</option>
|
||||||
|
<option value="LI">Lipkovo</option>
|
||||||
|
<option value="LO">Lozovo</option>
|
||||||
|
<option value="MR">Mavrovo i Rostu\xc5\xa1a</option>
|
||||||
|
<option value="MK">Makedonska Kamenica</option>
|
||||||
|
<option value="MD">Makedonski Brod</option>
|
||||||
|
<option value="MG">Mogila</option>
|
||||||
|
<option value="NG">Negotino</option>
|
||||||
|
<option value="NV">Novaci</option>
|
||||||
|
<option value="NS">Novo Selo</option>
|
||||||
|
<option value="OS">Oslomej</option>
|
||||||
|
<option value="OD" selected="selected">Ohrid</option>
|
||||||
|
<option value="PE">Petrovec</option>
|
||||||
|
<option value="PH">Peh\xc4\x8devo</option>
|
||||||
|
<option value="PN">Plasnica</option>
|
||||||
|
<option value="PP">Prilep</option>
|
||||||
|
<option value="PT">Probi\xc5\xa1tip</option>
|
||||||
|
<option value="RV">Radovi\xc5\xa1</option>
|
||||||
|
<option value="RN">Rankovce</option>
|
||||||
|
<option value="RE">Resen</option>
|
||||||
|
<option value="RO">Rosoman</option>
|
||||||
|
<option value="AJ">Saraj</option>
|
||||||
|
<option value="SL">Sveti Nikole</option>
|
||||||
|
<option value="SS">Sopi\xc5\xa1te</option>
|
||||||
|
<option value="SD">Star Dojran</option>
|
||||||
|
<option value="NA">Staro Nagori\xc4\x8dane</option>
|
||||||
|
<option value="UG">Struga</option>
|
||||||
|
<option value="RU">Strumica</option>
|
||||||
|
<option value="SU">Studeni\xc4\x8dani</option>
|
||||||
|
<option value="TR">Tearce</option>
|
||||||
|
<option value="ET">Tetovo</option>
|
||||||
|
<option value="CE">Centar</option>
|
||||||
|
<option value="CZ">Centar-\xc5\xbdupa</option>
|
||||||
|
<option value="CI">\xc4\x8cair</option>
|
||||||
|
<option value="CA">\xc4\x8ca\xc5\xa1ka</option>
|
||||||
|
<option value="CH">\xc4\x8ce\xc5\xa1inovo-Oble\xc5\xa1evo</option>
|
||||||
|
<option value="CS">\xc4\x8cu\xc4\x8der-Sandevo</option>
|
||||||
|
<option value="ST">\xc5\xa0tip</option>
|
||||||
|
<option value="SO">\xc5\xa0uto Orizari</option>
|
||||||
|
</select>"""
|
||||||
|
self.assertEqual(str(self.form['municipality']), municipality_select_html)
|
|
@ -2,5 +2,7 @@ from django.test import TestCase
|
||||||
from django.utils import unittest
|
from django.utils import unittest
|
||||||
|
|
||||||
# just import your tests here
|
# just import your tests here
|
||||||
from us.tests import *
|
|
||||||
from au.tests import *
|
from au.tests import *
|
||||||
|
from mk.tests import *
|
||||||
|
from us.tests import *
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue