Skip to content

Commit

Permalink
Fixed #17864 -- Added Hong Kong localflavor. Thanks to mrkschan and A…
Browse files Browse the repository at this point in the history
…drien Lemaire.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@17886 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information
jphalip committed Apr 9, 2012
1 parent 883c38c commit 6f7aa51
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 0 deletions.
Empty file.
71 changes: 71 additions & 0 deletions django/contrib/localflavor/hk/forms.py
@@ -0,0 +1,71 @@
"""
Hong Kong specific Form helpers
"""
from __future__ import absolute_import

import re

from django.core.validators import EMPTY_VALUES
from django.forms import CharField
from django.forms import ValidationError
from django.utils.encoding import smart_unicode
from django.utils.translation import ugettext_lazy as _


hk_phone_digits_re = re.compile(r'^(?:852-?)?(\d{4})[-\.]?(\d{4})$')
hk_special_numbers = ('999', '992', '112')
hk_phone_prefixes = ('2', '3', '5', '6', '8', '9')
hk_formats = ['XXXX-XXXX', '852-XXXX-XXXX', '(+852) XXXX-XXXX',
'XXXX XXXX', 'XXXXXXXX']



class HKPhoneNumberField(CharField):
"""
Validate Hong Kong phone number.
The input format can be either one of the followings:
'XXXX-XXXX', '852-XXXX-XXXX', '(+852) XXXX-XXXX',
'XXXX XXXX', or 'XXXXXXXX'.
The output format is 'XXXX-XXXX'.
Note: The phone number shall not start with 999, 992, or 112.
And, it should start with either 2, 3, 5, 6, 8, or 9.
Ref - http://en.wikipedia.org/wiki/Telephone_numbers_in_Hong_Kong
"""
default_error_messages = {
'disguise': _('Phone number should not start with ' \
'one of the followings: %s.' % \
', '.join(hk_special_numbers)),
'invalid': _('Phone number must be in one of the following formats: '
'%s.' % ', '.join(hk_formats)),
'prefix': _('Phone number should start with ' \
'one of the followings: %s.' % \
', '.join(hk_phone_prefixes)),
}

def __init__(self, *args, **kwargs):
super(HKPhoneNumberField, self).__init__(*args, **kwargs)

def clean(self, value):
super(HKPhoneNumberField, self).clean(value)

if value in EMPTY_VALUES:
return u''

value = re.sub('(\(|\)|\s+|\+)', '', smart_unicode(value))
m = hk_phone_digits_re.search(value)
if not m:
raise ValidationError(self.error_messages['invalid'])

value = u'%s-%s' % (m.group(1), m.group(2))
for special in hk_special_numbers:
if value.startswith(special):
raise ValidationError(self.error_messages['disguise'])

prefix_found = map(lambda prefix: value.startswith(prefix),
hk_phone_prefixes)
if not any(prefix_found):
raise ValidationError(self.error_messages['prefix'])

return value
10 changes: 10 additions & 0 deletions docs/ref/contrib/localflavor.txt
Expand Up @@ -51,6 +51,7 @@ Countries currently supported by :mod:`~django.contrib.localflavor` are:
* Finland_ * Finland_
* France_ * France_
* Germany_ * Germany_
* `Hong Kong`_
* Iceland_ * Iceland_
* India_ * India_
* Indonesia_ * Indonesia_
Expand Down Expand Up @@ -108,6 +109,7 @@ Here's an example of how to use them::
.. _Finland: `Finland (fi)`_ .. _Finland: `Finland (fi)`_
.. _France: `France (fr)`_ .. _France: `France (fr)`_
.. _Germany: `Germany (de)`_ .. _Germany: `Germany (de)`_
.. _Hong Kong: `Hong Kong (hk)`_
.. _The Netherlands: `The Netherlands (nl)`_ .. _The Netherlands: `The Netherlands (nl)`_
.. _Iceland: `Iceland (is\_)`_ .. _Iceland: `Iceland (is\_)`_
.. _India: `India (in\_)`_ .. _India: `India (in\_)`_
Expand Down Expand Up @@ -560,6 +562,14 @@ Germany (``de``)


A ``Select`` widget that uses a list of German states as its choices. A ``Select`` widget that uses a list of German states as its choices.


Hong Kong (``hk``)
==================

.. class:: hk.forms.HKPhoneNumberField

A form field that validates input as a Hong Kong phone number.


The Netherlands (``nl``) The Netherlands (``nl``)
======================== ========================


Expand Down
Empty file.
11 changes: 11 additions & 0 deletions tests/regressiontests/localflavor/hk/forms.py
@@ -0,0 +1,11 @@
from __future__ import absolute_import

from django.forms import ModelForm

from .models import HKPlace


class HKPlaceForm(ModelForm):

class Meta:
model = HKPlace
35 changes: 35 additions & 0 deletions tests/regressiontests/localflavor/hk/tests.py
@@ -0,0 +1,35 @@
from __future__ import absolute_import

from django.contrib.localflavor.hk.forms import HKPhoneNumberField
from django.test import SimpleTestCase


class HKLocalFlavorTests(SimpleTestCase):
"""Tests for Hong Kong Local Flavors"""

def test_HKPhoneNumberField(self):
error_msgs = HKPhoneNumberField.default_error_messages
valid = {
'2111-1111': '2111-1111',
'3111 1111': '3111-1111',
'51111111': '5111-1111',
'852-6111-1111': '6111-1111',
'(+852) 8111-1111': '8111-1111',
'(+852) 9111-1111': '9111-1111',
'85291111111': '9111-1111',
}
invalid = {
'9991-1111': [error_msgs['disguise'], ],
'9921-1111': [error_msgs['disguise'], ],
'1121-1111': [error_msgs['disguise'], ],
'99987654': [error_msgs['disguise'], ],
'99287654': [error_msgs['disguise'], ],
'11287654': [error_msgs['disguise'], ],
'1': [error_msgs['invalid'], ],
'2111--1111': [error_msgs['invalid'], ],
'11111111': [error_msgs['prefix'], ],
'00000000': [error_msgs['prefix'], ],
'44444444': [error_msgs['prefix'], ],
'77777777': [error_msgs['prefix'], ],
}
self.assertFieldOutput(HKPhoneNumberField, valid, invalid)
1 change: 1 addition & 0 deletions tests/regressiontests/localflavor/tests.py
Expand Up @@ -18,6 +18,7 @@
from .fr.tests import FRLocalFlavorTests from .fr.tests import FRLocalFlavorTests
from .gb.tests import GBLocalFlavorTests from .gb.tests import GBLocalFlavorTests
from .generic.tests import GenericLocalFlavorTests from .generic.tests import GenericLocalFlavorTests
from .hk.tests import HKLocalFlavorTests
from .hr.tests import HRLocalFlavorTests from .hr.tests import HRLocalFlavorTests
from .id.tests import IDLocalFlavorTests from .id.tests import IDLocalFlavorTests
from .ie.tests import IELocalFlavorTests from .ie.tests import IELocalFlavorTests
Expand Down

0 comments on commit 6f7aa51

Please sign in to comment.