Commits

Anonymous committed 50b3263

Fixed #14608 -- Added phone number field to Indian local flavor. Thanks, lawgon and Julien Phalip.

Comments (0)

Files changed (3)

django/contrib/localflavor/in_/forms.py

 
 from django.core.validators import EMPTY_VALUES
 from django.forms import ValidationError
-from django.forms.fields import Field, RegexField, Select
+from django.forms.fields import Field, RegexField, CharField, Select
 from django.utils.encoding import smart_unicode
 from django.utils.translation import ugettext_lazy as _
 
+phone_digits_re = re.compile(r"""
+(
+    (?P<std_code>                   # the std-code group
+        ^0                          # all std-codes start with 0
+        (
+            (?P<twodigit>\d{2})   | # either two, three or four digits
+            (?P<threedigit>\d{3}) | # following the 0
+            (?P<fourdigit>\d{4})
+        )
+    )
+    [-\s]                           # space or -
+    (?P<phone_no>                   # the phone number group
+        [1-6]                       # first digit of phone number
+        (
+            (?(twodigit)\d{7})   |  # 7 more phone digits for 3 digit stdcode
+            (?(threedigit)\d{6}) |  # 6 more phone digits for 4 digit stdcode
+            (?(fourdigit)\d{5})     # 5 more phone digits for 5 digit stdcode
+        )
+    )
+)$""", re.VERBOSE)
+
 
 class INZipCodeField(RegexField):
     default_error_messages = {
         value = re.sub(r'^(\d{3})\s(\d{3})$', r'\1\2', value)
         return value
 
+
 class INStateField(Field):
     """
     A form field that validates its input is a Indian state name or
                 pass
         raise ValidationError(self.error_messages['invalid'])
 
+
 class INStateSelect(Select):
     """
     A Select widget that uses a list of Indian states/territories as its
         from in_states import STATE_CHOICES
         super(INStateSelect, self).__init__(attrs, choices=STATE_CHOICES)
 
+
+class INPhoneNumberField(CharField):
+    """
+    INPhoneNumberField validates that the data is a valid Indian phone number,
+    including the STD code. It's normalised to 0XXX-XXXXXXX or 0XXX XXXXXXX
+    format. The first string is the STD code which is a '0' followed by 2-4
+    digits. The second string is 8 digits if the STD code is 3 digits, 7
+    digits if the STD code is 4 digits and 6 digits if the STD code is 5
+    digits. The second string will start with numbers between 1 and 6. The
+    separator is either a space or a hyphen.
+    """
+    default_error_messages = {
+        'invalid': _('Phone numbers must be in 02X-8X or 03X-7X or 04X-6X format.'),
+    }
+
+    def clean(self, value):
+        super(INPhoneNumberField, self).clean(value)
+        if value in EMPTY_VALUES:
+            return u''
+        value = smart_unicode(value)
+        m = phone_digits_re.match(value)
+        if m:
+            return u'%s' % (value)
+        raise ValidationError(self.error_messages['invalid'])
+

docs/ref/contrib/localflavor.txt

 India (``in_``)
 ===============
 
-.. class:: in.forms.INStateField
+.. class:: in_.forms.INStateField
 
     A form field that validates input as an Indian state/territory name or
     abbreviation. Input is normalized to the standard two-letter vehicle
     registration abbreviation for the given state or territory.
 
-.. class:: in.forms.INZipCodeField
+.. class:: in_.forms.INZipCodeField
 
     A form field that validates input as an Indian zip code, with the
     format XXXXXXX.
 
-.. class:: in.forms.INStateSelect
+.. class:: in_.forms.INStateSelect
 
     A ``Select`` widget that uses a list of Indian states/territories as its
     choices.
 
+.. versionadded:: 1.4
+
+.. class:: in_.forms.INPhoneNumberField
+
+    A form field that validates that the data is a valid Indian phone number,
+    including the STD code. It's normalised to 0XXX-XXXXXXX or 0XXX XXXXXXX
+    format. The first string is the STD code which is a '0' followed by 2-4
+    digits. The second string is 8 digits if the STD code is 3 digits, 7
+    digits if the STD code is 4 digits and 6 digits if the STD code is 5
+    digits. The second string will start with numbers between 1 and 6. The
+    separator is either a space or a hyphen.
+
 Ireland (``ie``)
 ================
 

tests/regressiontests/forms/localflavor/in_.py

 import warnings
 
 from django.contrib.localflavor.in_.forms import (INZipCodeField,
-                                                  INStateField, INStateSelect)
+    INStateField, INStateSelect, INPhoneNumberField)
 
 from utils import LocalFlavorTestCase
 
 
+
 class INLocalFlavorTests(LocalFlavorTestCase):
+    def test_INPhoneNumberField(self):
+        error_format = [u'Phone numbers must be in 02X-8X or 03X-7X or 04X-6X format.']
+        valid = {
+            '0423-2443667': '0423-2443667',
+            '0423 2443667': '0423 2443667',
+            '04236-244366': '04236-244366',
+            '040-24436678': '040-24436678',
+        }
+        invalid = {
+            '04-2443667': error_format,
+            '423-2443667': error_format,
+            '0423-9442667': error_format,
+            '0423-0443667': error_format,
+            '0423-244366': error_format,
+            '04232442667': error_format,
+            '0423DJANGO': error_format,
+        }
+        self.assertFieldOutput(INPhoneNumberField, valid, invalid)
+
     def test_INPStateSelect(self):
         f = INStateSelect()
         out = u'''<select name="state">
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.