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_
|
||||
* Sweden_
|
||||
* Switzerland_
|
||||
* Turkey_
|
||||
* `United Kingdom`_
|
||||
* `United States of America`_
|
||||
* Uruguay_
|
||||
|
@ -115,6 +116,7 @@ Here's an example of how to use them::
|
|||
.. _Spain: `Spain (es)`_
|
||||
.. _Sweden: `Sweden (se)`_
|
||||
.. _Switzerland: `Switzerland (ch)`_
|
||||
.. _Turkey: `Turkey (tr)`_
|
||||
.. _United Kingdom: `United Kingdom (uk)`_
|
||||
.. _United States of America: `United States of America (us)`_
|
||||
.. _Uruguay: `Uruguay (uy)`_
|
||||
|
@ -853,6 +855,35 @@ Switzerland (``ch``)
|
|||
|
||||
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``)
|
||||
=======================
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ from django.forms import *
|
|||
from django.contrib.localflavor.be.forms import (BEPostalCodeField,
|
||||
BEPhoneNumberField, BERegionSelect, BEProvinceSelect)
|
||||
|
||||
class BETests(TestCase):
|
||||
class BELocalFlavorTests(TestCase):
|
||||
"""
|
||||
Test case to validate BE localflavor
|
||||
"""
|
||||
|
|
|
@ -4,7 +4,7 @@ from django.core.exceptions import ValidationError
|
|||
from django.utils.unittest import TestCase
|
||||
|
||||
|
||||
class IsraelLocalFlavorTests(TestCase):
|
||||
class ILLocalFlavorTests(TestCase):
|
||||
def test_postal_code_field(self):
|
||||
f = ILPostalCodeField()
|
||||
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.id import tests as localflavor_id_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.it import tests as localflavor_it_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.se import tests as localflavor_se_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.us import tests as localflavor_us_tests
|
||||
from localflavor.uy import tests as localflavor_uy_tests
|
||||
from localflavor.za import tests as localflavor_za_tests
|
||||
|
||||
from localflavor.be import BETests
|
||||
from localflavor.be import BELocalFlavorTests
|
||||
|
||||
__test__ = {
|
||||
'localflavor_ar_tests': localflavor_ar_tests,
|
||||
|
|
|
@ -11,5 +11,10 @@ from util import *
|
|||
from validators import TestFieldWithValidators
|
||||
from widgets import *
|
||||
|
||||
from regressiontests.forms.localflavortests import (__test__, BETests,
|
||||
DELocalFlavorTests, IsraelLocalFlavorTests)
|
||||
from regressiontests.forms.localflavortests import (
|
||||
__test__,
|
||||
BELocalFlavorTests,
|
||||
DELocalFlavorTests,
|
||||
ILLocalFlavorTests,
|
||||
TRLocalFlavorTests
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue