Fixed #14563 -- Added Turkish localflavor. Thanks to serkank for the patch.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@14794 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
34a386378f
commit
ae7213b593
|
@ -0,0 +1,91 @@
|
||||||
|
"""
|
||||||
|
TR-specific Form helpers
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.core.validators import EMPTY_VALUES
|
||||||
|
from django.forms import ValidationError
|
||||||
|
from django.forms.fields import Field, RegexField, Select, CharField
|
||||||
|
from django.utils.encoding import smart_unicode
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
import re
|
||||||
|
|
||||||
|
phone_digits_re = re.compile(r'^(\+90|0)? ?(([1-9]\d{2})|\([1-9]\d{2}\)) ?([2-9]\d{2} ?\d{2} ?\d{2})$')
|
||||||
|
|
||||||
|
class TRPostalCodeField(RegexField):
|
||||||
|
default_error_messages = {
|
||||||
|
'invalid': _(u'Enter a postal code in the format XXXXX.'),
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(TRPostalCodeField, self).__init__(r'^\d{5}$',
|
||||||
|
max_length=5, min_length=5, *args, **kwargs)
|
||||||
|
|
||||||
|
def clean(self, value):
|
||||||
|
value = super(TRPostalCodeField, self).clean(value)
|
||||||
|
if value in EMPTY_VALUES:
|
||||||
|
return u''
|
||||||
|
if len(value) != 5:
|
||||||
|
raise ValidationError(self.error_messages['invalid'])
|
||||||
|
province_code = int(value[:2])
|
||||||
|
if province_code == 0 or province_code > 81:
|
||||||
|
raise ValidationError(self.error_messages['invalid'])
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
class TRPhoneNumberField(CharField):
|
||||||
|
default_error_messages = {
|
||||||
|
'invalid': _(u'Phone numbers must be in 0XXX XXX XXXX format.'),
|
||||||
|
}
|
||||||
|
|
||||||
|
def clean(self, value):
|
||||||
|
super(TRPhoneNumberField, self).clean(value)
|
||||||
|
if value in EMPTY_VALUES:
|
||||||
|
return u''
|
||||||
|
value = re.sub('(\(|\)|\s+)', '', smart_unicode(value))
|
||||||
|
m = phone_digits_re.search(value)
|
||||||
|
if m:
|
||||||
|
return u'%s%s' % (m.group(2), m.group(4))
|
||||||
|
raise ValidationError(self.error_messages['invalid'])
|
||||||
|
|
||||||
|
class TRIdentificationNumberField(Field):
|
||||||
|
"""
|
||||||
|
A Turkey Identification Number number.
|
||||||
|
See: http://tr.wikipedia.org/wiki/T%C3%BCrkiye_Cumhuriyeti_Kimlik_Numaras%C4%B1
|
||||||
|
|
||||||
|
Checks the following rules to determine whether the number is valid:
|
||||||
|
|
||||||
|
* The number is 11-digits.
|
||||||
|
* First digit is not 0.
|
||||||
|
* Conforms to the following two formula:
|
||||||
|
(sum(1st, 3rd, 5th, 7th, 9th)*7 - sum(2nd,4th,6th,8th)) % 10 = 10th digit
|
||||||
|
sum(1st to 10th) % 10 = 11th digit
|
||||||
|
"""
|
||||||
|
default_error_messages = {
|
||||||
|
'invalid': _(u'Enter a valid Turkish Identification number.'),
|
||||||
|
'not_11': _(u'Turkish Identification number must be 11 digits.'),
|
||||||
|
}
|
||||||
|
|
||||||
|
def clean(self, value):
|
||||||
|
super(TRIdentificationNumberField, self).clean(value)
|
||||||
|
if value in EMPTY_VALUES:
|
||||||
|
return u''
|
||||||
|
if len(value) != 11:
|
||||||
|
raise ValidationError(self.error_messages['not_11'])
|
||||||
|
if not re.match(r'^\d{11}$', value):
|
||||||
|
raise ValidationError(self.error_messages['invalid'])
|
||||||
|
if int(value[0]) == 0:
|
||||||
|
raise ValidationError(self.error_messages['invalid'])
|
||||||
|
chksum = (sum([int(value[i]) for i in xrange(0,9,2)])*7-
|
||||||
|
sum([int(value[i]) for i in xrange(1,9,2)])) % 10
|
||||||
|
if chksum != int(value[9]) or \
|
||||||
|
(sum([int(value[i]) for i in xrange(10)]) % 10) != int(value[10]):
|
||||||
|
raise ValidationError(self.error_messages['invalid'])
|
||||||
|
return value
|
||||||
|
|
||||||
|
class TRProvinceSelect(Select):
|
||||||
|
"""
|
||||||
|
A Select widget that uses a list of provinces in Turkey as its choices.
|
||||||
|
"""
|
||||||
|
def __init__(self, attrs=None):
|
||||||
|
from tr_provinces import PROVINCE_CHOICES
|
||||||
|
super(TRProvinceSelect, self).__init__(attrs, choices=PROVINCE_CHOICES)
|
|
@ -0,0 +1,89 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
This exists in this standalone file so that it's only imported into memory
|
||||||
|
when explicitly needed.
|
||||||
|
"""
|
||||||
|
|
||||||
|
PROVINCE_CHOICES = (
|
||||||
|
('01', ('Adana')),
|
||||||
|
('02', ('Adıyaman')),
|
||||||
|
('03', ('Afyonkarahisar')),
|
||||||
|
('04', ('Ağrı')),
|
||||||
|
('68', ('Aksaray')),
|
||||||
|
('05', ('Amasya')),
|
||||||
|
('06', ('Ankara')),
|
||||||
|
('07', ('Antalya')),
|
||||||
|
('75', ('Ardahan')),
|
||||||
|
('08', ('Artvin')),
|
||||||
|
('09', ('Aydın')),
|
||||||
|
('10', ('Balıkesir')),
|
||||||
|
('74', ('Bartın')),
|
||||||
|
('72', ('Batman')),
|
||||||
|
('69', ('Bayburt')),
|
||||||
|
('11', ('Bilecik')),
|
||||||
|
('12', ('Bingöl')),
|
||||||
|
('13', ('Bitlis')),
|
||||||
|
('14', ('Bolu')),
|
||||||
|
('15', ('Burdur')),
|
||||||
|
('16', ('Bursa')),
|
||||||
|
('17', ('Çanakkale')),
|
||||||
|
('18', ('Çankırı')),
|
||||||
|
('19', ('Çorum')),
|
||||||
|
('20', ('Denizli')),
|
||||||
|
('21', ('Diyarbakır')),
|
||||||
|
('81', ('Düzce')),
|
||||||
|
('22', ('Edirne')),
|
||||||
|
('23', ('Elazığ')),
|
||||||
|
('24', ('Erzincan')),
|
||||||
|
('25', ('Erzurum')),
|
||||||
|
('26', ('Eskişehir')),
|
||||||
|
('27', ('Gaziantep')),
|
||||||
|
('28', ('Giresun')),
|
||||||
|
('29', ('Gümüşhane')),
|
||||||
|
('30', ('Hakkari')),
|
||||||
|
('31', ('Hatay')),
|
||||||
|
('76', ('Iğdır')),
|
||||||
|
('32', ('Isparta')),
|
||||||
|
('33', ('Mersin')),
|
||||||
|
('34', ('İstanbul')),
|
||||||
|
('35', ('İzmir')),
|
||||||
|
('78', ('Karabük')),
|
||||||
|
('36', ('Kars')),
|
||||||
|
('37', ('Kastamonu')),
|
||||||
|
('38', ('Kayseri')),
|
||||||
|
('39', ('Kırklareli')),
|
||||||
|
('40', ('Kırşehir')),
|
||||||
|
('41', ('Kocaeli')),
|
||||||
|
('42', ('Konya')),
|
||||||
|
('43', ('Kütahya')),
|
||||||
|
('44', ('Malatya')),
|
||||||
|
('45', ('Manisa')),
|
||||||
|
('46', ('Kahramanmaraş')),
|
||||||
|
('70', ('Karaman')),
|
||||||
|
('71', ('Kırıkkale')),
|
||||||
|
('79', ('Kilis')),
|
||||||
|
('47', ('Mardin')),
|
||||||
|
('48', ('Muğla')),
|
||||||
|
('49', ('Muş')),
|
||||||
|
('50', ('Nevşehir')),
|
||||||
|
('51', ('Niğde')),
|
||||||
|
('52', ('Ordu')),
|
||||||
|
('80', ('Osmaniye')),
|
||||||
|
('53', ('Rize')),
|
||||||
|
('54', ('Sakarya')),
|
||||||
|
('55', ('Samsun')),
|
||||||
|
('56', ('Siirt')),
|
||||||
|
('57', ('Sinop')),
|
||||||
|
('58', ('Sivas')),
|
||||||
|
('73', ('Şırnak')),
|
||||||
|
('59', ('Tekirdağ')),
|
||||||
|
('60', ('Tokat')),
|
||||||
|
('61', ('Trabzon')),
|
||||||
|
('62', ('Tunceli')),
|
||||||
|
('63', ('Şanlıurfa')),
|
||||||
|
('64', ('Uşak')),
|
||||||
|
('65', ('Van')),
|
||||||
|
('77', ('Yalova')),
|
||||||
|
('66', ('Yozgat')),
|
||||||
|
('67', ('Zonguldak')),
|
||||||
|
)
|
|
@ -67,6 +67,7 @@ Countries currently supported by :mod:`~django.contrib.localflavor` are:
|
||||||
* Spain_
|
* Spain_
|
||||||
* Sweden_
|
* Sweden_
|
||||||
* Switzerland_
|
* Switzerland_
|
||||||
|
* Turkey_
|
||||||
* `United Kingdom`_
|
* `United Kingdom`_
|
||||||
* `United States of America`_
|
* `United States of America`_
|
||||||
* Uruguay_
|
* Uruguay_
|
||||||
|
@ -115,6 +116,7 @@ Here's an example of how to use them::
|
||||||
.. _Spain: `Spain (es)`_
|
.. _Spain: `Spain (es)`_
|
||||||
.. _Sweden: `Sweden (se)`_
|
.. _Sweden: `Sweden (se)`_
|
||||||
.. _Switzerland: `Switzerland (ch)`_
|
.. _Switzerland: `Switzerland (ch)`_
|
||||||
|
.. _Turkey: `Turkey (tr)`_
|
||||||
.. _United Kingdom: `United Kingdom (uk)`_
|
.. _United Kingdom: `United Kingdom (uk)`_
|
||||||
.. _United States of America: `United States of America (us)`_
|
.. _United States of America: `United States of America (us)`_
|
||||||
.. _Uruguay: `Uruguay (uy)`_
|
.. _Uruguay: `Uruguay (uy)`_
|
||||||
|
@ -853,6 +855,35 @@ Switzerland (``ch``)
|
||||||
|
|
||||||
A ``Select`` widget that uses a list of Swiss states as its choices.
|
A ``Select`` widget that uses a list of Swiss states as its choices.
|
||||||
|
|
||||||
|
Turkey (``tr``)
|
||||||
|
===============
|
||||||
|
|
||||||
|
.. class:: tr.forms.TRZipCodeField
|
||||||
|
|
||||||
|
A form field that validates input as a Turkish zip code. Valid codes
|
||||||
|
consist of five digits.
|
||||||
|
|
||||||
|
.. class:: tr.forms.TRPhoneNumberField
|
||||||
|
|
||||||
|
A form field that validates input as a Turkish phone number. The correct
|
||||||
|
format is 0xxx xxx xxxx. +90xxx xxx xxxx and inputs without spaces also
|
||||||
|
validates. The result is normalized to xxx xxx xxxx format.
|
||||||
|
|
||||||
|
.. class:: tr.forms.TRIdentificationNumberField
|
||||||
|
|
||||||
|
A form field that validates input as a TR identification number. A valid
|
||||||
|
number must satisfy the following:
|
||||||
|
|
||||||
|
* The number consist of 11 digits.
|
||||||
|
* The first digit cannot be 0.
|
||||||
|
* (sum(1st, 3rd, 5th, 7th, 9th)*7 - sum(2nd,4th,6th,8th)) % 10) must be
|
||||||
|
equal to the 10th digit.
|
||||||
|
* (sum(1st to 10th) % 10) must be equal to the 11th digit.
|
||||||
|
|
||||||
|
.. class:: tr.forms.TRProvinceSelect
|
||||||
|
|
||||||
|
A ``select`` widget that uses a list of Turkish provinces as its choices.
|
||||||
|
|
||||||
United Kingdom (``uk``)
|
United Kingdom (``uk``)
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ from django.forms import *
|
||||||
from django.contrib.localflavor.be.forms import (BEPostalCodeField,
|
from django.contrib.localflavor.be.forms import (BEPostalCodeField,
|
||||||
BEPhoneNumberField, BERegionSelect, BEProvinceSelect)
|
BEPhoneNumberField, BERegionSelect, BEProvinceSelect)
|
||||||
|
|
||||||
class BETests(TestCase):
|
class BELocalFlavorTests(TestCase):
|
||||||
"""
|
"""
|
||||||
Test case to validate BE localflavor
|
Test case to validate BE localflavor
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -4,7 +4,7 @@ from django.core.exceptions import ValidationError
|
||||||
from django.utils.unittest import TestCase
|
from django.utils.unittest import TestCase
|
||||||
|
|
||||||
|
|
||||||
class IsraelLocalFlavorTests(TestCase):
|
class ILLocalFlavorTests(TestCase):
|
||||||
def test_postal_code_field(self):
|
def test_postal_code_field(self):
|
||||||
f = ILPostalCodeField()
|
f = ILPostalCodeField()
|
||||||
self.assertRaisesRegexp(ValidationError,
|
self.assertRaisesRegexp(ValidationError,
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
# Tests for the contrib/localflavor/ TR form fields.
|
||||||
|
|
||||||
|
from django.contrib.localflavor.tr import forms as trforms
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
|
from django.utils.unittest import TestCase
|
||||||
|
|
||||||
|
class TRLocalFlavorTests(TestCase):
|
||||||
|
def test_TRPostalCodeField(self):
|
||||||
|
f = trforms.TRPostalCodeField()
|
||||||
|
self.assertEqual(f.clean("06531"), "06531")
|
||||||
|
self.assertEqual(f.clean("12345"), "12345")
|
||||||
|
self.assertRaisesRegexp(ValidationError,
|
||||||
|
"Enter a postal code in the format XXXXX.",
|
||||||
|
f.clean, "a1234")
|
||||||
|
self.assertRaisesRegexp(ValidationError,
|
||||||
|
"Enter a postal code in the format XXXXX.",
|
||||||
|
f.clean, "1234")
|
||||||
|
self.assertRaisesRegexp(ValidationError,
|
||||||
|
"Enter a postal code in the format XXXXX.",
|
||||||
|
f.clean, "82123")
|
||||||
|
self.assertRaisesRegexp(ValidationError,
|
||||||
|
"Enter a postal code in the format XXXXX.",
|
||||||
|
f.clean, "00123")
|
||||||
|
self.assertRaisesRegexp(ValidationError,
|
||||||
|
"Enter a postal code in the format XXXXX.",
|
||||||
|
f.clean, "123456")
|
||||||
|
self.assertRaisesRegexp(ValidationError,
|
||||||
|
"Enter a postal code in the format XXXXX.",
|
||||||
|
f.clean, "12 34")
|
||||||
|
self.assertRaises(ValidationError, f.clean, None)
|
||||||
|
|
||||||
|
def test_TRPhoneNumberField(self):
|
||||||
|
f = trforms.TRPhoneNumberField()
|
||||||
|
self.assertEqual(f.clean("312 455 56 78"), "3124555678")
|
||||||
|
self.assertEqual(f.clean("312 4555678"), "3124555678")
|
||||||
|
self.assertEqual(f.clean("3124555678"), "3124555678")
|
||||||
|
self.assertEqual(f.clean("0312 455 5678"), "3124555678")
|
||||||
|
self.assertEqual(f.clean("0 312 455 5678"), "3124555678")
|
||||||
|
self.assertEqual(f.clean("0 (312) 455 5678"), "3124555678")
|
||||||
|
self.assertEqual(f.clean("+90 312 455 4567"), "3124554567")
|
||||||
|
self.assertEqual(f.clean("+90 312 455 45 67"), "3124554567")
|
||||||
|
self.assertEqual(f.clean("+90 (312) 4554567"), "3124554567")
|
||||||
|
self.assertRaisesRegexp(ValidationError,
|
||||||
|
'Phone numbers must be in 0XXX XXX XXXX format.',
|
||||||
|
f.clean, "1234 233 1234")
|
||||||
|
self.assertRaisesRegexp(ValidationError,
|
||||||
|
'Phone numbers must be in 0XXX XXX XXXX format.',
|
||||||
|
f.clean, "0312 233 12345")
|
||||||
|
self.assertRaisesRegexp(ValidationError,
|
||||||
|
'Phone numbers must be in 0XXX XXX XXXX format.',
|
||||||
|
f.clean, "0312 233 123")
|
||||||
|
self.assertRaisesRegexp(ValidationError,
|
||||||
|
'Phone numbers must be in 0XXX XXX XXXX format.',
|
||||||
|
f.clean, "0312 233 xxxx")
|
||||||
|
|
||||||
|
def test_TRIdentificationNumberField(self):
|
||||||
|
f = trforms.TRIdentificationNumberField()
|
||||||
|
self.assertEqual(f.clean("10000000146"), "10000000146")
|
||||||
|
self.assertRaisesRegexp(ValidationError,
|
||||||
|
'Enter a valid Turkish Identification number.',
|
||||||
|
f.clean, "10000000136")
|
||||||
|
self.assertRaisesRegexp(ValidationError,
|
||||||
|
'Enter a valid Turkish Identification number.',
|
||||||
|
f.clean, "10000000147")
|
||||||
|
self.assertRaisesRegexp(ValidationError,
|
||||||
|
'Turkish Identification number must be 11 digits.',
|
||||||
|
f.clean, "123456789")
|
||||||
|
self.assertRaisesRegexp(ValidationError,
|
||||||
|
'Enter a valid Turkish Identification number.',
|
||||||
|
f.clean, "1000000014x")
|
||||||
|
self.assertRaisesRegexp(ValidationError,
|
||||||
|
'Enter a valid Turkish Identification number.',
|
||||||
|
f.clean, "x0000000146")
|
|
@ -14,7 +14,7 @@ from localflavor.fr import tests as localflavor_fr_tests
|
||||||
from localflavor.generic import tests as localflavor_generic_tests
|
from localflavor.generic import tests as localflavor_generic_tests
|
||||||
from localflavor.id import tests as localflavor_id_tests
|
from localflavor.id import tests as localflavor_id_tests
|
||||||
from localflavor.ie import tests as localflavor_ie_tests
|
from localflavor.ie import tests as localflavor_ie_tests
|
||||||
from localflavor.il import IsraelLocalFlavorTests
|
from localflavor.il import ILLocalFlavorTests
|
||||||
from localflavor.is_ import tests as localflavor_is_tests
|
from localflavor.is_ import tests as localflavor_is_tests
|
||||||
from localflavor.it import tests as localflavor_it_tests
|
from localflavor.it import tests as localflavor_it_tests
|
||||||
from localflavor.jp import tests as localflavor_jp_tests
|
from localflavor.jp import tests as localflavor_jp_tests
|
||||||
|
@ -25,12 +25,13 @@ from localflavor.pt import tests as localflavor_pt_tests
|
||||||
from localflavor.ro import tests as localflavor_ro_tests
|
from localflavor.ro import tests as localflavor_ro_tests
|
||||||
from localflavor.se import tests as localflavor_se_tests
|
from localflavor.se import tests as localflavor_se_tests
|
||||||
from localflavor.sk import tests as localflavor_sk_tests
|
from localflavor.sk import tests as localflavor_sk_tests
|
||||||
|
from localflavor.tr import TRLocalFlavorTests
|
||||||
from localflavor.uk import tests as localflavor_uk_tests
|
from localflavor.uk import tests as localflavor_uk_tests
|
||||||
from localflavor.us import tests as localflavor_us_tests
|
from localflavor.us import tests as localflavor_us_tests
|
||||||
from localflavor.uy import tests as localflavor_uy_tests
|
from localflavor.uy import tests as localflavor_uy_tests
|
||||||
from localflavor.za import tests as localflavor_za_tests
|
from localflavor.za import tests as localflavor_za_tests
|
||||||
|
|
||||||
from localflavor.be import BETests
|
from localflavor.be import BELocalFlavorTests
|
||||||
|
|
||||||
__test__ = {
|
__test__ = {
|
||||||
'localflavor_ar_tests': localflavor_ar_tests,
|
'localflavor_ar_tests': localflavor_ar_tests,
|
||||||
|
|
|
@ -11,5 +11,10 @@ from util import *
|
||||||
from validators import TestFieldWithValidators
|
from validators import TestFieldWithValidators
|
||||||
from widgets import *
|
from widgets import *
|
||||||
|
|
||||||
from regressiontests.forms.localflavortests import (__test__, BETests,
|
from regressiontests.forms.localflavortests import (
|
||||||
DELocalFlavorTests, IsraelLocalFlavorTests)
|
__test__,
|
||||||
|
BELocalFlavorTests,
|
||||||
|
DELocalFlavorTests,
|
||||||
|
ILLocalFlavorTests,
|
||||||
|
TRLocalFlavorTests
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue