Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed #4143 -- Added Icelandic localflavor. Note that we use the is_/…

… directory

name because "is" is a reserved word in Python. Patch from
django@einaregilsson.com.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@5080 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit a738f3a4ff01c54d05a214cf8771f93f29152c1e 1 parent 37e4842
@malcolmt malcolmt authored
View
0  django/contrib/localflavor/is_/__init__.py
No changes.
View
81 django/contrib/localflavor/is_/forms.py
@@ -0,0 +1,81 @@
+"""
+Iceland specific form helpers.
+"""
+from django.newforms import ValidationError
+from django.newforms.fields import RegexField, EMPTY_VALUES
+from django.newforms.widgets import Select
+from django.utils.translation import gettext
+
+
+class ISIdNumberField(RegexField):
+ """
+ Icelandic identification number (kennitala). This is a number every citizen
+ of Iceland has.
+ """
+ def __init__(self, *args, **kwargs):
+ error_msg = gettext(u'Enter a valid Icelandic identification number. The format is XXXXXX-XXXX.')
+ kwargs['min_length'],kwargs['max_length'] = 10,11
+
+ super(ISIdNumberField, self).__init__(r'^\d{6}(-| )?\d{4}$', error_message=error_msg, *args, **kwargs)
+
+ def clean(self, value):
+ value = super(ISIdNumberField, self).clean(value)
+
+ if value in EMPTY_VALUES:
+ return u''
+
+ value = self._canonify(value)
+ if self._validate(value):
+ return self._format(value)
+ else:
+ raise ValidationError(gettext(u'The Icelandic identification number is not valid.'))
+
+
+ def _canonify(self, value):
+ """
+ Returns the value as only digits.
+ """
+ return value.replace('-', '').replace(' ', '')
+
+ def _validate(self, value):
+ """
+ Takes in the value in canonical form and checks the verifier digit. The
+ method is modulo 11.
+ """
+ check = [3, 2, 7, 6, 5, 4, 3, 2, 1, 0]
+ return sum(int(value[i]) * check[i] for i in range(10)) % 11 == 0
+
+ def _format(self, value):
+ """
+ Takes in the value in canonical form and returns it in the common
+ display format.
+ """
+ return value[:6]+'-'+value[6:]
+
+
+class ISPhoneNumberField(RegexField):
+ """
+ Icelandic phone number. Seven digits with an optional hyphen or space after
+ the first three digits.
+ """
+ def __init__(self, *args, **kwargs):
+ kwargs['min_length'], kwargs['max_length'] = 7,8
+ super(ISPhoneNumberField, self).__init__(r'^\d{3}(-| )?\d{4}$', *args, **kwargs)
+
+ def clean(self, value):
+ value = super(ISPhoneNumberField, self).clean(value)
+
+ if value in EMPTY_VALUES:
+ return u''
+
+ return value.replace('-', '').replace(' ', '')
+
+
+class ISPostalCodeSelect(Select):
+ """
+ A Select widget that uses a list of Icelandic postal codes as its choices.
+ """
+ def __init__(self, attrs=None):
+ from is_postalcodes import IS_POSTALCODES
+ super(ISPostalCodeSelect, self).__init__(attrs, choices=IS_POSTALCODES)
+
View
151 django/contrib/localflavor/is_/is_postalcodes.py
@@ -0,0 +1,151 @@
+# -*- coding: utf-8 -*-
+
+IS_POSTALCODES = (
+ ('101', u'101 Reykjavík'),
+ ('103', u'103 Reykjavík'),
+ ('104', u'104 Reykjavík'),
+ ('105', u'105 Reykjavík'),
+ ('107', u'107 Reykjavík'),
+ ('108', u'108 Reykjavík'),
+ ('109', u'109 Reykjavík'),
+ ('110', u'110 Reykjavík'),
+ ('111', u'111 Reykjavík'),
+ ('112', u'112 Reykjavík'),
+ ('113', u'113 Reykjavík'),
+ ('116', u'116 Kjalarnes'),
+ ('121', u'121 Reykjavík'),
+ ('123', u'123 Reykjavík'),
+ ('124', u'124 Reykjavík'),
+ ('125', u'125 Reykjavík'),
+ ('127', u'127 Reykjavík'),
+ ('128', u'128 Reykjavík'),
+ ('129', u'129 Reykjavík'),
+ ('130', u'130 Reykjavík'),
+ ('132', u'132 Reykjavík'),
+ ('150', u'150 Reykjavík'),
+ ('155', u'155 Reykjavík'),
+ ('170', u'170 Seltjarnarnes'),
+ ('172', u'172 Seltjarnarnes'),
+ ('190', u'190 Vogar'),
+ ('200', u'200 Kópavogur'),
+ ('201', u'201 Kópavogur'),
+ ('202', u'202 Kópavogur'),
+ ('203', u'203 Kópavogur'),
+ ('210', u'210 Garðabær'),
+ ('212', u'212 Garðabær'),
+ ('220', u'220 Hafnarfjörður'),
+ ('221', u'221 Hafnarfjörður'),
+ ('222', u'222 Hafnarfjörður'),
+ ('225', u'225 Álftanes'),
+ ('230', u'230 Reykjanesbær'),
+ ('232', u'232 Reykjanesbær'),
+ ('233', u'233 Reykjanesbær'),
+ ('235', u'235 Keflavíkurflugvöllur'),
+ ('240', u'240 Grindavík'),
+ ('245', u'245 Sandgerði'),
+ ('250', u'250 Garður'),
+ ('260', u'260 Reykjanesbær'),
+ ('270', u'270 Mosfellsbær'),
+ ('300', u'300 Akranes'),
+ ('301', u'301 Akranes'),
+ ('302', u'302 Akranes'),
+ ('310', u'310 Borgarnes'),
+ ('311', u'311 Borgarnes'),
+ ('320', u'320 Reykholt í Borgarfirði'),
+ ('340', u'340 Stykkishólmur'),
+ ('345', u'345 Flatey á Breiðafirði'),
+ ('350', u'350 Grundarfjörður'),
+ ('355', u'355 Ólafsvík'),
+ ('356', u'356 Snæfellsbær'),
+ ('360', u'360 Hellissandur'),
+ ('370', u'370 Búðardalur'),
+ ('371', u'371 Búðardalur'),
+ ('380', u'380 Reykhólahreppur'),
+ ('400', u'400 Ísafjörður'),
+ ('401', u'401 Ísafjörður'),
+ ('410', u'410 Hnífsdalur'),
+ ('415', u'415 Bolungarvík'),
+ ('420', u'420 Súðavík'),
+ ('425', u'425 Flateyri'),
+ ('430', u'430 Suðureyri'),
+ ('450', u'450 Patreksfjörður'),
+ ('451', u'451 Patreksfjörður'),
+ ('460', u'460 Tálknafjörður'),
+ ('465', u'465 Bíldudalur'),
+ ('470', u'470 Þingeyri'),
+ ('471', u'471 Þingeyri'),
+ ('500', u'500 Staður'),
+ ('510', u'510 Hólmavík'),
+ ('512', u'512 Hólmavík'),
+ ('520', u'520 Drangsnes'),
+ ('522', u'522 Kjörvogur'),
+ ('523', u'523 Bær'),
+ ('524', u'524 Norðurfjörður'),
+ ('530', u'530 Hvammstangi'),
+ ('531', u'531 Hvammstangi'),
+ ('540', u'540 Blönduós'),
+ ('541', u'541 Blönduós'),
+ ('545', u'545 Skagaströnd'),
+ ('550', u'550 Sauðárkrókur'),
+ ('551', u'551 Sauðárkrókur'),
+ ('560', u'560 Varmahlíð'),
+ ('565', u'565 Hofsós'),
+ ('566', u'566 Hofsós'),
+ ('570', u'570 Fljót'),
+ ('580', u'580 Siglufjörður'),
+ ('600', u'600 Akureyri'),
+ ('601', u'601 Akureyri'),
+ ('602', u'602 Akureyri'),
+ ('603', u'603 Akureyri'),
+ ('610', u'610 Grenivík'),
+ ('611', u'611 Grímsey'),
+ ('620', u'620 Dalvík'),
+ ('621', u'621 Dalvík'),
+ ('625', u'625 Ólafsfjörður'),
+ ('630', u'630 Hrísey'),
+ ('640', u'640 Húsavík'),
+ ('641', u'641 Húsavík'),
+ ('645', u'645 Fosshóll'),
+ ('650', u'650 Laugar'),
+ ('660', u'660 Mývatn'),
+ ('670', u'670 Kópasker'),
+ ('671', u'671 Kópasker'),
+ ('675', u'675 Raufarhöfn'),
+ ('680', u'680 Þórshöfn'),
+ ('681', u'681 Þórshöfn'),
+ ('685', u'685 Bakkafjörður'),
+ ('690', u'690 Vopnafjörður'),
+ ('700', u'700 Egilsstaðir'),
+ ('701', u'701 Egilsstaðir'),
+ ('710', u'710 Seyðisfjörður'),
+ ('715', u'715 Mjóifjörður'),
+ ('720', u'720 Borgarfjörður eystri'),
+ ('730', u'730 Reyðarfjörður'),
+ ('735', u'735 Eskifjörður'),
+ ('740', u'740 Neskaupstaður'),
+ ('750', u'750 Fáskrúðsfjörður'),
+ ('755', u'755 Stöðvarfjörður'),
+ ('760', u'760 Breiðdalsvík'),
+ ('765', u'765 Djúpivogur'),
+ ('780', u'780 Höfn í Hornafirði'),
+ ('781', u'781 Höfn í Hornafirði'),
+ ('785', u'785 Öræfi'),
+ ('800', u'800 Selfoss'),
+ ('801', u'801 Selfoss'),
+ ('802', u'802 Selfoss'),
+ ('810', u'810 Hveragerði'),
+ ('815', u'815 Þorlákshöfn'),
+ ('820', u'820 Eyrarbakki'),
+ ('825', u'825 Stokkseyri'),
+ ('840', u'840 Laugarvatn'),
+ ('845', u'845 Flúðir'),
+ ('850', u'850 Hella'),
+ ('851', u'851 Hella'),
+ ('860', u'860 Hvolsvöllur'),
+ ('861', u'861 Hvolsvöllur'),
+ ('870', u'870 Vík'),
+ ('871', u'871 Vík'),
+ ('880', u'880 Kirkjubæjarklaustur'),
+ ('900', u'900 Vestmannaeyjar'),
+ ('902', u'902 Vestmannaeyjar')
+)
View
98 tests/regressiontests/forms/localflavor.py
@@ -1052,4 +1052,102 @@
<option value="VIC">Victoria</option>
<option value="WA">Western Australia</option>
</select>
+
+## ISIdNumberField #############################################################
+
+>>> from django.contrib.localflavor.is_.forms import *
+>>> f = ISIdNumberField()
+>>> f.clean('2308803449')
+u'230880-3449'
+>>> f.clean('230880-3449')
+u'230880-3449'
+>>> f.clean('230880 3449')
+u'230880-3449'
+>>> f.clean('230880343')
+Traceback (most recent call last):
+...
+ValidationError: [u'Ensure this value has at least 10 characters.']
+>>> f.clean('230880343234')
+Traceback (most recent call last):
+...
+ValidationError: [u'Ensure this value has at most 11 characters.']
+>>> f.clean('abcdefghijk')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a valid Icelandic identification number. The format is XXXXXX-XXXX.']
+>>> f.clean('')
+Traceback (most recent call last):
+...
+ValidationError: [u'This field is required.']
+>>> f.clean(None)
+Traceback (most recent call last):
+...
+ValidationError: [u'This field is required.']
+>>> f.clean('2308803439')
+Traceback (most recent call last):
+...
+ValidationError: [u'The Icelandic identification number is not valid.']
+>>> f.clean('2308803440')
+u'230880-3440'
+>>> f = ISIdNumberField(required=False)
+>>> f.clean(None)
+u''
+>>> f.clean('')
+u''
+
+## ISPhoneNumberField #############################################################
+
+>>> from django.contrib.localflavor.is_.forms import *
+>>> f = ISPhoneNumberField()
+>>> f.clean('1234567')
+u'1234567'
+>>> f.clean('123 4567')
+u'1234567'
+>>> f.clean('123-4567')
+u'1234567'
+>>> f.clean('123-456')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a valid value.']
+>>> f.clean('123456')
+Traceback (most recent call last):
+...
+ValidationError: [u'Ensure this value has at least 7 characters.']
+>>> f.clean('123456555')
+Traceback (most recent call last):
+...
+ValidationError: [u'Ensure this value has at most 8 characters.']
+>>> f.clean('abcdefg')
+Traceback (most recent call last):
+ValidationError: [u'Enter a valid value.']
+>>> f.clean(' 1234567 ')
+Traceback (most recent call last):
+...
+ValidationError: [u'Ensure this value has at most 8 characters.']
+>>> f.clean(' 12367 ')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a valid value.']
+
+>>> f.clean('')
+Traceback (most recent call last):
+...
+ValidationError: [u'This field is required.']
+>>> f.clean(None)
+Traceback (most recent call last):
+...
+ValidationError: [u'This field is required.']
+>>> f = ISPhoneNumberField(required=False)
+>>> f.clean(None)
+u''
+>>> f.clean('')
+u''
+
+## ISPostalCodeSelect #############################################################
+
+>>> from django.contrib.localflavor.is_.forms import *
+>>> f = ISPostalCodeSelect()
+
+>>> f.render('foo', 'bar')
+u'<select name="foo">\n<option value="101">101 Reykjav\xedk</option>\n<option value="103">103 Reykjav\xedk</option>\n<option value="104">104 Reykjav\xedk</option>\n<option value="105">105 Reykjav\xedk</option>\n<option value="107">107 Reykjav\xedk</option>\n<option value="108">108 Reykjav\xedk</option>\n<option value="109">109 Reykjav\xedk</option>\n<option value="110">110 Reykjav\xedk</option>\n<option value="111">111 Reykjav\xedk</option>\n<option value="112">112 Reykjav\xedk</option>\n<option value="113">113 Reykjav\xedk</option>\n<option value="116">116 Kjalarnes</option>\n<option value="121">121 Reykjav\xedk</option>\n<option value="123">123 Reykjav\xedk</option>\n<option value="124">124 Reykjav\xedk</option>\n<option value="125">125 Reykjav\xedk</option>\n<option value="127">127 Reykjav\xedk</option>\n<option value="128">128 Reykjav\xedk</option>\n<option value="129">129 Reykjav\xedk</option>\n<option value="130">130 Reykjav\xedk</option>\n<option value="132">132 Reykjav\xedk</option>\n<option value="150">150 Reykjav\xedk</option>\n<option value="155">155 Reykjav\xedk</option>\n<option value="170">170 Seltjarnarnes</option>\n<option value="172">172 Seltjarnarnes</option>\n<option value="190">190 Vogar</option>\n<option value="200">200 K\xf3pavogur</option>\n<option value="201">201 K\xf3pavogur</option>\n<option value="202">202 K\xf3pavogur</option>\n<option value="203">203 K\xf3pavogur</option>\n<option value="210">210 Gar\xf0ab\xe6r</option>\n<option value="212">212 Gar\xf0ab\xe6r</option>\n<option value="220">220 Hafnarfj\xf6r\xf0ur</option>\n<option value="221">221 Hafnarfj\xf6r\xf0ur</option>\n<option value="222">222 Hafnarfj\xf6r\xf0ur</option>\n<option value="225">225 \xc1lftanes</option>\n<option value="230">230 Reykjanesb\xe6r</option>\n<option value="232">232 Reykjanesb\xe6r</option>\n<option value="233">233 Reykjanesb\xe6r</option>\n<option value="235">235 Keflav\xedkurflugv\xf6llur</option>\n<option value="240">240 Grindav\xedk</option>\n<option value="245">245 Sandger\xf0i</option>\n<option value="250">250 Gar\xf0ur</option>\n<option value="260">260 Reykjanesb\xe6r</option>\n<option value="270">270 Mosfellsb\xe6r</option>\n<option value="300">300 Akranes</option>\n<option value="301">301 Akranes</option>\n<option value="302">302 Akranes</option>\n<option value="310">310 Borgarnes</option>\n<option value="311">311 Borgarnes</option>\n<option value="320">320 Reykholt \xed Borgarfir\xf0i</option>\n<option value="340">340 Stykkish\xf3lmur</option>\n<option value="345">345 Flatey \xe1 Brei\xf0afir\xf0i</option>\n<option value="350">350 Grundarfj\xf6r\xf0ur</option>\n<option value="355">355 \xd3lafsv\xedk</option>\n<option value="356">356 Sn\xe6fellsb\xe6r</option>\n<option value="360">360 Hellissandur</option>\n<option value="370">370 B\xfa\xf0ardalur</option>\n<option value="371">371 B\xfa\xf0ardalur</option>\n<option value="380">380 Reykh\xf3lahreppur</option>\n<option value="400">400 \xcdsafj\xf6r\xf0ur</option>\n<option value="401">401 \xcdsafj\xf6r\xf0ur</option>\n<option value="410">410 Hn\xedfsdalur</option>\n<option value="415">415 Bolungarv\xedk</option>\n<option value="420">420 S\xfa\xf0av\xedk</option>\n<option value="425">425 Flateyri</option>\n<option value="430">430 Su\xf0ureyri</option>\n<option value="450">450 Patreksfj\xf6r\xf0ur</option>\n<option value="451">451 Patreksfj\xf6r\xf0ur</option>\n<option value="460">460 T\xe1lknafj\xf6r\xf0ur</option>\n<option value="465">465 B\xedldudalur</option>\n<option value="470">470 \xdeingeyri</option>\n<option value="471">471 \xdeingeyri</option>\n<option value="500">500 Sta\xf0ur</option>\n<option value="510">510 H\xf3lmav\xedk</option>\n<option value="512">512 H\xf3lmav\xedk</option>\n<option value="520">520 Drangsnes</option>\n<option value="522">522 Kj\xf6rvogur</option>\n<option value="523">523 B\xe6r</option>\n<option value="524">524 Nor\xf0urfj\xf6r\xf0ur</option>\n<option value="530">530 Hvammstangi</option>\n<option value="531">531 Hvammstangi</option>\n<option value="540">540 Bl\xf6ndu\xf3s</option>\n<option value="541">541 Bl\xf6ndu\xf3s</option>\n<option value="545">545 Skagastr\xf6nd</option>\n<option value="550">550 Sau\xf0\xe1rkr\xf3kur</option>\n<option value="551">551 Sau\xf0\xe1rkr\xf3kur</option>\n<option value="560">560 Varmahl\xed\xf0</option>\n<option value="565">565 Hofs\xf3s</option>\n<option value="566">566 Hofs\xf3s</option>\n<option value="570">570 Flj\xf3t</option>\n<option value="580">580 Siglufj\xf6r\xf0ur</option>\n<option value="600">600 Akureyri</option>\n<option value="601">601 Akureyri</option>\n<option value="602">602 Akureyri</option>\n<option value="603">603 Akureyri</option>\n<option value="610">610 Greniv\xedk</option>\n<option value="611">611 Gr\xedmsey</option>\n<option value="620">620 Dalv\xedk</option>\n<option value="621">621 Dalv\xedk</option>\n<option value="625">625 \xd3lafsfj\xf6r\xf0ur</option>\n<option value="630">630 Hr\xedsey</option>\n<option value="640">640 H\xfasav\xedk</option>\n<option value="641">641 H\xfasav\xedk</option>\n<option value="645">645 Fossh\xf3ll</option>\n<option value="650">650 Laugar</option>\n<option value="660">660 M\xfdvatn</option>\n<option value="670">670 K\xf3pasker</option>\n<option value="671">671 K\xf3pasker</option>\n<option value="675">675 Raufarh\xf6fn</option>\n<option value="680">680 \xde\xf3rsh\xf6fn</option>\n<option value="681">681 \xde\xf3rsh\xf6fn</option>\n<option value="685">685 Bakkafj\xf6r\xf0ur</option>\n<option value="690">690 Vopnafj\xf6r\xf0ur</option>\n<option value="700">700 Egilssta\xf0ir</option>\n<option value="701">701 Egilssta\xf0ir</option>\n<option value="710">710 Sey\xf0isfj\xf6r\xf0ur</option>\n<option value="715">715 Mj\xf3ifj\xf6r\xf0ur</option>\n<option value="720">720 Borgarfj\xf6r\xf0ur eystri</option>\n<option value="730">730 Rey\xf0arfj\xf6r\xf0ur</option>\n<option value="735">735 Eskifj\xf6r\xf0ur</option>\n<option value="740">740 Neskaupsta\xf0ur</option>\n<option value="750">750 F\xe1skr\xfa\xf0sfj\xf6r\xf0ur</option>\n<option value="755">755 St\xf6\xf0varfj\xf6r\xf0ur</option>\n<option value="760">760 Brei\xf0dalsv\xedk</option>\n<option value="765">765 Dj\xfapivogur</option>\n<option value="780">780 H\xf6fn \xed Hornafir\xf0i</option>\n<option value="781">781 H\xf6fn \xed Hornafir\xf0i</option>\n<option value="785">785 \xd6r\xe6fi</option>\n<option value="800">800 Selfoss</option>\n<option value="801">801 Selfoss</option>\n<option value="802">802 Selfoss</option>\n<option value="810">810 Hverager\xf0i</option>\n<option value="815">815 \xdeorl\xe1ksh\xf6fn</option>\n<option value="820">820 Eyrarbakki</option>\n<option value="825">825 Stokkseyri</option>\n<option value="840">840 Laugarvatn</option>\n<option value="845">845 Fl\xfa\xf0ir</option>\n<option value="850">850 Hella</option>\n<option value="851">851 Hella</option>\n<option value="860">860 Hvolsv\xf6llur</option>\n<option value="861">861 Hvolsv\xf6llur</option>\n<option value="870">870 V\xedk</option>\n<option value="871">871 V\xedk</option>\n<option value="880">880 Kirkjub\xe6jarklaustur</option>\n<option value="900">900 Vestmannaeyjar</option>\n<option value="902">902 Vestmannaeyjar</option>\n</select>'
"""
Please sign in to comment.
Something went wrong with that request. Please try again.