Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #11350 -- added an Israeli localflavor. Thanks to Yuval and Ida…

…n Gazit for their work on the patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@14223 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 5a8e40a03fd03f3ab88fb21845dd704833f3f133 1 parent 2e8bc8f
Alex Gaynor authored
65  django/contrib/localflavor/il/forms.py
... ...
@@ -0,0 +1,65 @@
  1
+"""
  2
+Israeli-specific form helpers
  3
+"""
  4
+import re
  5
+
  6
+from django.core.exceptions import ValidationError
  7
+from django.forms.fields import RegexField, Field, EMPTY_VALUES
  8
+from django.utils.checksums import luhn
  9
+from django.utils.translation import ugettext_lazy as _
  10
+
  11
+# Israeli ID numbers consist of up to 8 digits followed by a checksum digit.
  12
+# Numbers which are shorter than 8 digits are effectively left-zero-padded.
  13
+# The checksum digit is occasionally separated from the number by a hyphen,
  14
+# and is calculated using the luhn algorithm.
  15
+#
  16
+# Relevant references:
  17
+#
  18
+# (hebrew) 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)
  19
+# (hebrew) http://he.wikipedia.org/wiki/%D7%A1%D7%A4%D7%A8%D7%AA_%D7%91%D7%99%D7%A7%D7%95%D7%A8%D7%AA
  20
+
  21
+id_number_re = re.compile(r'^(?P<number>\d{1,8})-?(?P<check>\d)$')
  22
+
  23
+class ILPostalCodeField(RegexField):
  24
+    """
  25
+    A form field that validates its input as an Israeli postal code.
  26
+    Valid form is XXXXX where X represents integer.
  27
+    """
  28
+
  29
+    default_error_messages = {
  30
+        'invalid': _(u'Enter a postal code in the format XXXXX'),
  31
+    }
  32
+
  33
+    def __init__(self, *args, **kwargs):
  34
+        super(ILPostalCodeField, self).__init__(r'^\d{5}$', *args, **kwargs)
  35
+
  36
+    def clean(self, value):
  37
+        if value is not None:
  38
+            value = value.replace(" ", "")
  39
+        return super(ILPostalCodeField, self).clean(value)
  40
+
  41
+
  42
+class ILIDNumberField(Field):
  43
+    """
  44
+    A form field that validates its input as an Israeli identification number.
  45
+    Valid form is per the Israeli ID specification.
  46
+    """
  47
+
  48
+    default_error_messages = {
  49
+        'invalid': _(u'Enter a valid ID number.'),
  50
+    }
  51
+
  52
+    def clean(self, value):
  53
+        value = super(ILIDNumberField, self).clean(value)
  54
+
  55
+        if value in EMPTY_VALUES:
  56
+            return u''
  57
+
  58
+        match = id_number_re.match(value)
  59
+        if not match:
  60
+            raise ValidationError(self.error_messages['invalid'])
  61
+
  62
+        value = match.group('number') + match.group('check')
  63
+        if not luhn(value):
  64
+            raise ValidationError(self.error_messages['invalid'])
  65
+        return value
24  docs/ref/contrib/localflavor.txt
@@ -51,6 +51,7 @@ Countries currently supported by :mod:`~django.contrib.localflavor` are:
51 51
     * India_
52 52
     * Indonesia_
53 53
     * Ireland_
  54
+    * Israel_
54 55
     * Italy_
55 56
     * Japan_
56 57
     * Kuwait_
@@ -99,6 +100,7 @@ Here's an example of how to use them::
99 100
 .. _India: `India (in\_)`_
100 101
 .. _Indonesia: `Indonesia (id)`_
101 102
 .. _Ireland: `Ireland (ie)`_
  103
+.. _Israel: `Israel (il)`_
102 104
 .. _Italy: `Italy (it)`_
103 105
 .. _Japan: `Japan (jp)`_
104 106
 .. _Kuwait: `Kuwait (kw)`_
@@ -446,6 +448,28 @@ Indonesia (``id``)
446 448
 
447 449
 .. _NIK: http://en.wikipedia.org/wiki/Indonesian_identity_card
448 450
 
  451
+Israel (``il``)
  452
+===============
  453
+
  454
+.. class: il.forms.ILPostalCodeField
  455
+
  456
+    A form field that validates its input as an Israeli five-digit postal code.
  457
+
  458
+.. class:: il.forms.ILIDNumberField
  459
+
  460
+    A form field that validates its input as an `Israeli identification number`_.
  461
+    The output will be in the format of a 2-9 digit number, consisting of a
  462
+    1-8 digit ID number followed by a single checksum digit, calculated using the `Luhn
  463
+    algorithm.`_.
  464
+
  465
+    Input may contain an optional hyphen separating the ID number from the checksum
  466
+    digit.
  467
+
  468
+.. _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)
  469
+.. _Luhn algorithm: http://en.wikipedia.org/wiki/Luhn_algorithm
  470
+
  471
+
  472
+
449 473
 Italy (``it``)
450 474
 ==============
451 475
 
0  localflavor/il/__init__.py b/django/contrib/localflavor/il/__init__.py
No changes.
57  tests/regressiontests/forms/localflavor/il.py
... ...
@@ -0,0 +1,57 @@
  1
+from django.contrib.localflavor.il.forms import (ILPostalCodeField,
  2
+    ILIDNumberField)
  3
+from django.core.exceptions import ValidationError
  4
+from django.utils.unittest import TestCase
  5
+
  6
+
  7
+class IsraelLocalFlavorTests(TestCase):
  8
+    def test_postal_code_field(self):
  9
+        f = ILPostalCodeField()
  10
+        self.assertRaisesRegexp(ValidationError,
  11
+            "Enter a postal code in the format XXXXX",
  12
+            f.clean, "84545x"
  13
+        )
  14
+        self.assertEqual(f.clean("69973"), "69973")
  15
+        self.assertEqual(f.clean("699 73"), "69973")
  16
+        self.assertEqual(f.clean("12345"), "12345")
  17
+        self.assertRaisesRegexp(ValidationError,
  18
+            "Enter a postal code in the format XXXXX",
  19
+            f.clean, "123456"
  20
+        )
  21
+        self.assertRaisesRegexp(ValidationError,
  22
+            "Enter a postal code in the format XXXXX",
  23
+            f.clean, "1234"
  24
+        )
  25
+        self.assertRaisesRegexp(ValidationError,
  26
+            "Enter a postal code in the format XXXXX",
  27
+            f.clean, "123 4"
  28
+        )
  29
+        self.assertRaises(ValidationError, f.clean, None)
  30
+
  31
+    def test_id_number_field(self):
  32
+        f = ILIDNumberField()
  33
+        self.assertEqual(f.clean("3933742-3"), "39337423")
  34
+        self.assertEqual(f.clean("39337423"), "39337423")
  35
+        self.assertEqual(f.clean("039337423"), "039337423")
  36
+        self.assertEqual(f.clean("03933742-3"), "039337423")
  37
+        self.assertEqual(f.clean("0091"), "0091")
  38
+        self.assertRaisesRegexp(ValidationError,
  39
+            "Enter a valid ID number.",
  40
+            f.clean, "123456789"
  41
+        )
  42
+        self.assertRaisesRegexp(ValidationError,
  43
+            "Enter a valid ID number.",
  44
+            f.clean, "12345678-9"
  45
+        )
  46
+        self.assertRaisesRegexp(ValidationError,
  47
+            "Enter a valid ID number.",
  48
+            f.clean, "012346578"
  49
+        )
  50
+        self.assertRaisesRegexp(ValidationError,
  51
+            "Enter a valid ID number.",
  52
+            f.clean, "012346578-"
  53
+        )
  54
+        self.assertRaisesRegexp(ValidationError,
  55
+            "Enter a valid ID number.",
  56
+            f.clean, "0001"
  57
+        )
1  tests/regressiontests/forms/tests.py
@@ -17,6 +17,7 @@
17 17
 from localflavor.generic import tests as localflavor_generic_tests
18 18
 from localflavor.id import tests as localflavor_id_tests
19 19
 from localflavor.ie import tests as localflavor_ie_tests
  20
+from localflavor.il import IsraelLocalFlavorTests
20 21
 from localflavor.is_ import tests as localflavor_is_tests
21 22
 from localflavor.it import tests as localflavor_it_tests
22 23
 from localflavor.jp import tests as localflavor_jp_tests

0 notes on commit 5a8e40a

Please sign in to comment.
Something went wrong with that request. Please try again.