Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #8612 - Added Indonesian (id) localflavor. Thanks to Ronny Hary…

…anto for the patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@12046 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit e0dc28df5517d44dab05c01d1e8855711dab6c0a 1 parent 1295282
Jannis Leidel authored January 01, 2010
1  AUTHORS
@@ -196,6 +196,7 @@ answer newbie questions, and generally made Django that much better:
196 196
     hambaloney
197 197
     Brian Harring <ferringb@gmail.com>
198 198
     Brant Harris
  199
+    Ronny Haryanto <http://ronny.haryan.to/>
199 200
     Hawkeye
200 201
     Joe Heck <http://www.rhonabwy.com/wp/>
201 202
     Joel Heenan <joelh-django@planetjoel.com>
210  django/contrib/localflavor/id/forms.py
... ...
@@ -0,0 +1,210 @@
  1
+"""
  2
+ID-specific Form helpers
  3
+"""
  4
+
  5
+import re
  6
+import time
  7
+
  8
+from django.forms import ValidationError
  9
+from django.forms.fields import Field, Select, EMPTY_VALUES
  10
+from django.utils.translation import ugettext_lazy as _
  11
+from django.utils.encoding import smart_unicode
  12
+
  13
+postcode_re = re.compile(r'^[1-9]\d{4}$')
  14
+phone_re = re.compile(r'^(\+62|0)[2-9]\d{7,10}$')
  15
+plate_re = re.compile(r'^(?P<prefix>[A-Z]{1,2}) ' + \
  16
+            r'(?P<number>\d{1,5})( (?P<suffix>([A-Z]{1,3}|[1-9][0-9]{,2})))?$')
  17
+nik_re = re.compile(r'^\d{16}$')
  18
+
  19
+
  20
+class IDPostCodeField(Field):
  21
+    """
  22
+    An Indonesian post code field.
  23
+
  24
+    http://id.wikipedia.org/wiki/Kode_pos
  25
+    """
  26
+    default_error_messages = {
  27
+        'invalid': _('Enter a valid post code'),
  28
+    }
  29
+
  30
+    def clean(self, value):
  31
+        super(IDPostCodeField, self).clean(value)
  32
+        if value in EMPTY_VALUES:
  33
+            return u''
  34
+
  35
+        value = value.strip()
  36
+        if not postcode_re.search(value):
  37
+            raise ValidationError(self.error_messages['invalid'])
  38
+
  39
+        if int(value) < 10110:
  40
+            raise ValidationError(self.error_messages['invalid'])
  41
+
  42
+        # 1xxx0
  43
+        if value[0] == '1' and value[4] != '0':
  44
+            raise ValidationError(self.error_messages['invalid'])
  45
+
  46
+        return u'%s' % (value, )
  47
+
  48
+
  49
+class IDProvinceSelect(Select):
  50
+    """
  51
+    A Select widget that uses a list of provinces of Indonesia as its
  52
+    choices.
  53
+    """
  54
+
  55
+    def __init__(self, attrs=None):
  56
+        from id_choices import PROVINCE_CHOICES
  57
+        super(IDProvinceSelect, self).__init__(attrs, choices=PROVINCE_CHOICES)
  58
+
  59
+
  60
+class IDPhoneNumberField(Field):
  61
+    """
  62
+    An Indonesian telephone number field.
  63
+
  64
+    http://id.wikipedia.org/wiki/Daftar_kode_telepon_di_Indonesia
  65
+    """
  66
+    default_error_messages = {
  67
+        'invalid': _('Enter a valid phone number'),
  68
+    }
  69
+
  70
+    def clean(self, value):
  71
+        super(IDPhoneNumberField, self).clean(value)
  72
+        if value in EMPTY_VALUES:
  73
+            return u''
  74
+
  75
+        phone_number = re.sub(r'[\-\s\(\)]', '', smart_unicode(value))
  76
+
  77
+        if phone_re.search(phone_number):
  78
+            return smart_unicode(value)
  79
+
  80
+        raise ValidationError(self.error_messages['invalid'])
  81
+
  82
+
  83
+class IDLicensePlatePrefixSelect(Select):
  84
+    """
  85
+    A Select widget that uses a list of vehicle license plate prefix code
  86
+    of Indonesia as its choices.
  87
+
  88
+    http://id.wikipedia.org/wiki/Tanda_Nomor_Kendaraan_Bermotor
  89
+    """
  90
+
  91
+    def __init__(self, attrs=None):
  92
+        from id_choices import LICENSE_PLATE_PREFIX_CHOICES
  93
+        super(IDLicensePlatePrefixSelect, self).__init__(attrs,
  94
+            choices=LICENSE_PLATE_PREFIX_CHOICES)
  95
+
  96
+
  97
+class IDLicensePlateField(Field):
  98
+    """
  99
+    An Indonesian vehicle license plate field.
  100
+
  101
+    http://id.wikipedia.org/wiki/Tanda_Nomor_Kendaraan_Bermotor
  102
+
  103
+    Plus: "B 12345 12"
  104
+    """
  105
+    default_error_messages = {
  106
+        'invalid': _('Enter a valid vehicle license plate number'),
  107
+    }
  108
+
  109
+    def clean(self, value):
  110
+        super(IDLicensePlateField, self).clean(value)
  111
+        if value in EMPTY_VALUES:
  112
+            return u''
  113
+
  114
+        plate_number = re.sub(r'\s+', ' ',
  115
+            smart_unicode(value.strip())).upper()
  116
+
  117
+        matches = plate_re.search(plate_number)
  118
+        if matches is None:
  119
+            raise ValidationError(self.error_messages['invalid'])
  120
+
  121
+        # Make sure prefix is in the list of known codes.
  122
+        from id_choices import LICENSE_PLATE_PREFIX_CHOICES
  123
+        prefix = matches.group('prefix')
  124
+        if prefix not in [choice[0] for choice in LICENSE_PLATE_PREFIX_CHOICES]:
  125
+            raise ValidationError(self.error_messages['invalid'])
  126
+
  127
+        # Only Jakarta (prefix B) can have 3 letter suffix.
  128
+        suffix = matches.group('suffix')
  129
+        if suffix is not None and len(suffix) == 3 and prefix != 'B':
  130
+            raise ValidationError(self.error_messages['invalid'])
  131
+
  132
+        # RI plates don't have suffix.
  133
+        if prefix == 'RI' and suffix is not None and suffix != '':
  134
+            raise ValidationError(self.error_messages['invalid'])
  135
+
  136
+        # Number can't be zero.
  137
+        number = matches.group('number')
  138
+        if number == '0':
  139
+            raise ValidationError(self.error_messages['invalid'])
  140
+
  141
+        # CD, CC and B 12345 12
  142
+        if len(number) == 5 or prefix in ('CD', 'CC'):
  143
+            # suffix must be numeric and non-empty
  144
+            if re.match(r'^\d+$', suffix) is None:
  145
+                raise ValidationError(self.error_messages['invalid'])
  146
+
  147
+            # Known codes range is 12-124
  148
+            if prefix in ('CD', 'CC') and not (12 <= int(number) <= 124):
  149
+                raise ValidationError(self.error_messages['invalid'])
  150
+            if len(number) == 5 and not (12 <= int(suffix) <= 124):
  151
+                raise ValidationError(self.error_messages['invalid'])
  152
+        else:
  153
+            # suffix must be non-numeric
  154
+            if suffix is not None and re.match(r'^[A-Z]{,3}$', suffix) is None:
  155
+                raise ValidationError(self.error_messages['invalid'])
  156
+
  157
+        return plate_number
  158
+
  159
+
  160
+class IDNationalIdentityNumberField(Field):
  161
+    """
  162
+    An Indonesian national identity number (NIK/KTP#) field.
  163
+
  164
+    http://id.wikipedia.org/wiki/Nomor_Induk_Kependudukan
  165
+
  166
+    xx.xxxx.ddmmyy.xxxx - 16 digits (excl. dots)
  167
+    """
  168
+    default_error_messages = {
  169
+        'invalid': _('Enter a valid NIK/KTP number'),
  170
+    }
  171
+
  172
+    def clean(self, value):
  173
+        super(IDNationalIdentityNumberField, self).clean(value)
  174
+        if value in EMPTY_VALUES:
  175
+            return u''
  176
+
  177
+        value = re.sub(r'[\s.]', '', smart_unicode(value))
  178
+
  179
+        if not nik_re.search(value):
  180
+            raise ValidationError(self.error_messages['invalid'])
  181
+
  182
+        if int(value) == 0:
  183
+            raise ValidationError(self.error_messages['invalid'])
  184
+
  185
+        def valid_nik_date(year, month, day):
  186
+            try:
  187
+                t1 = (int(year), int(month), int(day), 0, 0, 0, 0, 0, -1)
  188
+                d = time.mktime(t1)
  189
+                t2 = time.localtime(d)
  190
+                if t1[:3] != t2[:3]:
  191
+                    return False
  192
+                else:
  193
+                    return True
  194
+            except (OverflowError, ValueError):
  195
+                return False
  196
+
  197
+        year = int(value[10:12])
  198
+        month = int(value[8:10])
  199
+        day = int(value[6:8])
  200
+        current_year = time.localtime().tm_year
  201
+        if year < int(str(current_year)[-2:]):
  202
+            if not valid_nik_date(2000 + int(year), month, day):
  203
+                raise ValidationError(self.error_messages['invalid'])
  204
+        elif not valid_nik_date(1900 + int(year), month, day):
  205
+            raise ValidationError(self.error_messages['invalid'])
  206
+
  207
+        if value[:6] == '000000' or value[12:] == '0000':
  208
+            raise ValidationError(self.error_messages['invalid'])
  209
+
  210
+        return '%s.%s.%s.%s' % (value[:2], value[2:6], value[6:12], value[12:])
101  django/contrib/localflavor/id/id_choices.py
... ...
@@ -0,0 +1,101 @@
  1
+from django.utils.translation import ugettext_lazy as _
  2
+
  3
+# Reference: http://id.wikipedia.org/wiki/Daftar_provinsi_Indonesia
  4
+
  5
+# Indonesia does not have an official Province code standard.
  6
+# I decided to use unambiguous and consistent (some are common) 3-letter codes.
  7
+
  8
+PROVINCE_CHOICES = (
  9
+    ('BLI', _('Bali')),
  10
+    ('BTN', _('Banten')),
  11
+    ('BKL', _('Bengkulu')),
  12
+    ('DIY', _('Yogyakarta')),
  13
+    ('JKT', _('Jakarta')),
  14
+    ('GOR', _('Gorontalo')),
  15
+    ('JMB', _('Jambi')),
  16
+    ('JBR', _('Jawa Barat')),
  17
+    ('JTG', _('Jawa Tengah')),
  18
+    ('JTM', _('Jawa Timur')),
  19
+    ('KBR', _('Kalimantan Barat')),
  20
+    ('KSL', _('Kalimantan Selatan')),
  21
+    ('KTG', _('Kalimantan Tengah')),
  22
+    ('KTM', _('Kalimantan Timur')),
  23
+    ('BBL', _('Kepulauan Bangka-Belitung')),
  24
+    ('KRI', _('Kepulauan Riau')),
  25
+    ('LPG', _('Lampung')),
  26
+    ('MLK', _('Maluku')),
  27
+    ('MUT', _('Maluku Utara')),
  28
+    ('NAD', _('Nanggroe Aceh Darussalam')),
  29
+    ('NTB', _('Nusa Tenggara Barat')),
  30
+    ('NTT', _('Nusa Tenggara Timur')),
  31
+    ('PPA', _('Papua')),
  32
+    ('PPB', _('Papua Barat')),
  33
+    ('RIU', _('Riau')),
  34
+    ('SLB', _('Sulawesi Barat')),
  35
+    ('SLS', _('Sulawesi Selatan')),
  36
+    ('SLT', _('Sulawesi Tengah')),
  37
+    ('SLR', _('Sulawesi Tenggara')),
  38
+    ('SLU', _('Sulawesi Utara')),
  39
+    ('SMB', _('Sumatera Barat')),
  40
+    ('SMS', _('Sumatera Selatan')),
  41
+    ('SMU', _('Sumatera Utara')),
  42
+)
  43
+
  44
+LICENSE_PLATE_PREFIX_CHOICES = (
  45
+    ('A', _('Banten')),
  46
+    ('AA', _('Magelang')),
  47
+    ('AB', _('Yogyakarta')),
  48
+    ('AD', _('Surakarta - Solo')),
  49
+    ('AE', _('Madiun')),
  50
+    ('AG', _('Kediri')),
  51
+    ('B', _('Jakarta')),
  52
+    ('BA', _('Sumatera Barat')),
  53
+    ('BB', _('Tapanuli')),
  54
+    ('BD', _('Bengkulu')),
  55
+    ('BE', _('Lampung')),
  56
+    ('BG', _('Sumatera Selatan')),
  57
+    ('BH', _('Jambi')),
  58
+    ('BK', _('Sumatera Utara')),
  59
+    ('BL', _('Nanggroe Aceh Darussalam')),
  60
+    ('BM', _('Riau')),
  61
+    ('BN', _('Kepulauan Bangka Belitung')),
  62
+    ('BP', _('Kepulauan Riau')),
  63
+    ('CC', _('Corps Consulate')),
  64
+    ('CD', _('Corps Diplomatic')),
  65
+    ('D', _('Bandung')),
  66
+    ('DA', _('Kalimantan Selatan')),
  67
+    ('DB', _('Sulawesi Utara Daratan')),
  68
+    ('DC', _('Sulawesi Barat')),
  69
+    ('DD', _('Sulawesi Selatan')),
  70
+    ('DE', _('Maluku')),
  71
+    ('DG', _('Maluku Utara')),
  72
+    ('DH', _('NTT - Timor')),
  73
+    ('DK', _('Bali')),
  74
+    ('DL', _('Sulawesi Utara Kepulauan')),
  75
+    ('DM', _('Gorontalo')),
  76
+    ('DN', _('Sulawesi Tengah')),
  77
+    ('DR', _('NTB - Lombok')),
  78
+    ('DS', _('Papua dan Papua Barat')),
  79
+    ('DT', _('Sulawesi Tenggara')),
  80
+    ('E', _('Cirebon')),
  81
+    ('EA', _('NTB - Sumbawa')),
  82
+    ('EB', _('NTT - Flores')),
  83
+    ('ED', _('NTT - Sumba')),
  84
+    ('F', _('Bogor')),
  85
+    ('G', _('Pekalongan')),
  86
+    ('H', _('Semarang')),
  87
+    ('K', _('Pati')),
  88
+    ('KB', _('Kalimantan Barat')),
  89
+    ('KH', _('Kalimantan Tengah')),
  90
+    ('KT', _('Kalimantan Timur')),
  91
+    ('L', _('Surabaya')),
  92
+    ('M', _('Madura')),
  93
+    ('N', _('Malang')),
  94
+    ('P', _('Jember')),
  95
+    ('R', _('Banyumas')),
  96
+    ('RI', _('Federal Government')),
  97
+    ('S', _('Bojonegoro')),
  98
+    ('T', _('Purwakarta')),
  99
+    ('W', _('Sidoarjo')),
  100
+    ('Z', _('Garut')),
  101
+)
35  docs/ref/contrib/localflavor.txt
@@ -50,6 +50,7 @@ Countries currently supported by :mod:`~django.contrib.localflavor` are:
50 50
     * Germany_
51 51
     * Iceland_
52 52
     * India_
  53
+    * Indonesia_
53 54
     * Ireland_
54 55
     * Italy_
55 56
     * Japan_
@@ -95,6 +96,7 @@ Here's an example of how to use them::
95 96
 .. _The Netherlands: `The Netherlands (nl)`_
96 97
 .. _Iceland: `Iceland (is\_)`_
97 98
 .. _India: `India (in\_)`_
  99
+.. _Indonesia: `Indonesia (id)`_
98 100
 .. _Ireland: `Ireland (ie)`_
99 101
 .. _Italy: `Italy (it)`_
100 102
 .. _Japan: `Japan (jp)`_
@@ -382,6 +384,39 @@ Ireland (``ie``)
382 384
 
383 385
     A ``Select`` widget that uses a list of Irish Counties as its choices.
384 386
 
  387
+Indonesia (``id``)
  388
+==================
  389
+
  390
+.. class:: id.forms.IDPostCodeField
  391
+
  392
+    A form field that validates input as an Indonesian post code field.
  393
+
  394
+.. class:: id.forms.IDProvinceSelect
  395
+
  396
+    A ``Select`` widget that uses a list of Indonesian provinces as its choices.
  397
+
  398
+.. class:: id.forms.IDPhoneNumberField
  399
+
  400
+    A form field that validates input as an Indonesian telephone number.
  401
+
  402
+.. class:: id.forms.IDLicensePlatePrefixSelect
  403
+
  404
+    A ``Select`` widget that uses a list of Indonesian license plate
  405
+    prefix code as its choices.
  406
+
  407
+.. class:: id.forms.IDLicensePlateField
  408
+
  409
+    A form field that validates input as an Indonesian vehicle license plate.
  410
+
  411
+.. class:: id.forms.IDNationalIdentityNumberField
  412
+
  413
+    A form field that validates input as an Indonesian national identity
  414
+    number (`NIK`_/KTP). The output will be in the format of
  415
+    'XX.XXXX.DDMMYY.XXXX'. Dots or spaces can be used in the input to break
  416
+    down the numbers.
  417
+
  418
+.. _NIK: http://en.wikipedia.org/wiki/Indonesian_identity_card
  419
+
385 420
 Italy (``it``)
386 421
 ==============
387 422
 
0  localflavor/id/__init__.py b/django/contrib/localflavor/id/__init__.py
No changes.
175  tests/regressiontests/forms/localflavor/id.py
... ...
@@ -0,0 +1,175 @@
  1
+# -*- coding: utf-8 -*-
  2
+# Tests for the contrib/localflavor/ ID form fields.
  3
+
  4
+tests = r"""
  5
+
  6
+# IDPhoneNumberField ########################################################
  7
+
  8
+>>> from django.contrib.localflavor.id.forms import IDPhoneNumberField
  9
+>>> f = IDPhoneNumberField(required=False)
  10
+>>> f.clean('')
  11
+u''
  12
+>>> f.clean('0812-3456789')
  13
+u'0812-3456789'
  14
+>>> f.clean('081234567890')
  15
+u'081234567890'
  16
+>>> f.clean('021 345 6789')
  17
+u'021 345 6789'
  18
+>>> f.clean('0213456789')
  19
+u'0213456789'
  20
+>>> f.clean('0123456789')
  21
+Traceback (most recent call last):
  22
+    ...
  23
+ValidationError: [u'Enter a valid phone number']
  24
+>>> f.clean('+62-21-3456789')
  25
+u'+62-21-3456789'
  26
+>>> f.clean('+62-021-3456789')
  27
+Traceback (most recent call last):
  28
+    ...
  29
+ValidationError: [u'Enter a valid phone number']
  30
+>>> f.clean('(021) 345 6789')
  31
+u'(021) 345 6789'
  32
+>>> f.clean('+62-021-3456789')
  33
+Traceback (most recent call last):
  34
+    ...
  35
+ValidationError: [u'Enter a valid phone number']
  36
+>>> f.clean('+62-0812-3456789')
  37
+Traceback (most recent call last):
  38
+    ...
  39
+ValidationError: [u'Enter a valid phone number']
  40
+>>> f.clean('0812345678901')
  41
+Traceback (most recent call last):
  42
+    ...
  43
+ValidationError: [u'Enter a valid phone number']
  44
+>>> f.clean('foo')
  45
+Traceback (most recent call last):
  46
+    ...
  47
+ValidationError: [u'Enter a valid phone number']
  48
+
  49
+# IDPostCodeField ############################################################
  50
+
  51
+>>> from django.contrib.localflavor.id.forms import IDPostCodeField
  52
+>>> f = IDPostCodeField(required=False)
  53
+>>> f.clean('')
  54
+u''
  55
+>>> f.clean('12340')
  56
+u'12340'
  57
+>>> f.clean('25412')
  58
+u'25412'
  59
+>>> f.clean(' 12340 ')
  60
+u'12340'
  61
+>>> f.clean('12 3 4 0')
  62
+Traceback (most recent call last):
  63
+    ...
  64
+ValidationError: [u'Enter a valid post code']
  65
+>>> f.clean('12345')
  66
+Traceback (most recent call last):
  67
+    ...
  68
+ValidationError: [u'Enter a valid post code']
  69
+>>> f.clean('10100')
  70
+Traceback (most recent call last):
  71
+    ...
  72
+ValidationError: [u'Enter a valid post code']
  73
+>>> f.clean('123456')
  74
+Traceback (most recent call last):
  75
+    ...
  76
+ValidationError: [u'Enter a valid post code']
  77
+>>> f.clean('foo')
  78
+Traceback (most recent call last):
  79
+    ...
  80
+ValidationError: [u'Enter a valid post code']
  81
+
  82
+# IDNationalIdentityNumberField #########################################################
  83
+
  84
+>>> from django.contrib.localflavor.id.forms import IDNationalIdentityNumberField
  85
+>>> f = IDNationalIdentityNumberField(required=False)
  86
+>>> f.clean('')
  87
+u''
  88
+>>> f.clean(' 12.3456.010178 3456 ')
  89
+u'12.3456.010178.3456'
  90
+>>> f.clean('1234560101783456')
  91
+u'12.3456.010178.3456'
  92
+>>> f.clean('12.3456.010101.3456')
  93
+u'12.3456.010101.3456'
  94
+>>> f.clean('12.3456.310278.3456')
  95
+Traceback (most recent call last):
  96
+    ...
  97
+ValidationError: [u'Enter a valid NIK/KTP number']
  98
+>>> f.clean('00.0000.010101.0000')
  99
+Traceback (most recent call last):
  100
+    ...
  101
+ValidationError: [u'Enter a valid NIK/KTP number']
  102
+>>> f.clean('1234567890123456')
  103
+Traceback (most recent call last):
  104
+    ...
  105
+ValidationError: [u'Enter a valid NIK/KTP number']
  106
+>>> f.clean('foo')
  107
+Traceback (most recent call last):
  108
+    ...
  109
+ValidationError: [u'Enter a valid NIK/KTP number']
  110
+
  111
+# IDProvinceSelect ##########################################################
  112
+
  113
+>>> from django.contrib.localflavor.id.forms import IDProvinceSelect
  114
+>>> s = IDProvinceSelect()
  115
+>>> s.render('provinces', 'LPG')
  116
+u'<select name="provinces">\n<option value="BLI">Bali</option>\n<option value="BTN">Banten</option>\n<option value="BKL">Bengkulu</option>\n<option value="DIY">Yogyakarta</option>\n<option value="JKT">Jakarta</option>\n<option value="GOR">Gorontalo</option>\n<option value="JMB">Jambi</option>\n<option value="JBR">Jawa Barat</option>\n<option value="JTG">Jawa Tengah</option>\n<option value="JTM">Jawa Timur</option>\n<option value="KBR">Kalimantan Barat</option>\n<option value="KSL">Kalimantan Selatan</option>\n<option value="KTG">Kalimantan Tengah</option>\n<option value="KTM">Kalimantan Timur</option>\n<option value="BBL">Kepulauan Bangka-Belitung</option>\n<option value="KRI">Kepulauan Riau</option>\n<option value="LPG" selected="selected">Lampung</option>\n<option value="MLK">Maluku</option>\n<option value="MUT">Maluku Utara</option>\n<option value="NAD">Nanggroe Aceh Darussalam</option>\n<option value="NTB">Nusa Tenggara Barat</option>\n<option value="NTT">Nusa Tenggara Timur</option>\n<option value="PPA">Papua</option>\n<option value="PPB">Papua Barat</option>\n<option value="RIU">Riau</option>\n<option value="SLB">Sulawesi Barat</option>\n<option value="SLS">Sulawesi Selatan</option>\n<option value="SLT">Sulawesi Tengah</option>\n<option value="SLR">Sulawesi Tenggara</option>\n<option value="SLU">Sulawesi Utara</option>\n<option value="SMB">Sumatera Barat</option>\n<option value="SMS">Sumatera Selatan</option>\n<option value="SMU">Sumatera Utara</option>\n</select>'
  117
+
  118
+# IDLicensePlatePrefixelect ########################################################################
  119
+
  120
+>>> from django.contrib.localflavor.id.forms import IDLicensePlatePrefixSelect
  121
+>>> s = IDLicensePlatePrefixSelect()
  122
+>>> s.render('codes', 'BE')
  123
+u'<select name="codes">\n<option value="A">Banten</option>\n<option value="AA">Magelang</option>\n<option value="AB">Yogyakarta</option>\n<option value="AD">Surakarta - Solo</option>\n<option value="AE">Madiun</option>\n<option value="AG">Kediri</option>\n<option value="B">Jakarta</option>\n<option value="BA">Sumatera Barat</option>\n<option value="BB">Tapanuli</option>\n<option value="BD">Bengkulu</option>\n<option value="BE" selected="selected">Lampung</option>\n<option value="BG">Sumatera Selatan</option>\n<option value="BH">Jambi</option>\n<option value="BK">Sumatera Utara</option>\n<option value="BL">Nanggroe Aceh Darussalam</option>\n<option value="BM">Riau</option>\n<option value="BN">Kepulauan Bangka Belitung</option>\n<option value="BP">Kepulauan Riau</option>\n<option value="CC">Corps Consulate</option>\n<option value="CD">Corps Diplomatic</option>\n<option value="D">Bandung</option>\n<option value="DA">Kalimantan Selatan</option>\n<option value="DB">Sulawesi Utara Daratan</option>\n<option value="DC">Sulawesi Barat</option>\n<option value="DD">Sulawesi Selatan</option>\n<option value="DE">Maluku</option>\n<option value="DG">Maluku Utara</option>\n<option value="DH">NTT - Timor</option>\n<option value="DK">Bali</option>\n<option value="DL">Sulawesi Utara Kepulauan</option>\n<option value="DM">Gorontalo</option>\n<option value="DN">Sulawesi Tengah</option>\n<option value="DR">NTB - Lombok</option>\n<option value="DS">Papua dan Papua Barat</option>\n<option value="DT">Sulawesi Tenggara</option>\n<option value="E">Cirebon</option>\n<option value="EA">NTB - Sumbawa</option>\n<option value="EB">NTT - Flores</option>\n<option value="ED">NTT - Sumba</option>\n<option value="F">Bogor</option>\n<option value="G">Pekalongan</option>\n<option value="H">Semarang</option>\n<option value="K">Pati</option>\n<option value="KB">Kalimantan Barat</option>\n<option value="KH">Kalimantan Tengah</option>\n<option value="KT">Kalimantan Timur</option>\n<option value="L">Surabaya</option>\n<option value="M">Madura</option>\n<option value="N">Malang</option>\n<option value="P">Jember</option>\n<option value="R">Banyumas</option>\n<option value="RI">Federal Government</option>\n<option value="S">Bojonegoro</option>\n<option value="T">Purwakarta</option>\n<option value="W">Sidoarjo</option>\n<option value="Z">Garut</option>\n</select>'
  124
+
  125
+# IDLicensePlateField #######################################################################
  126
+
  127
+>>> from django.contrib.localflavor.id.forms import IDLicensePlateField
  128
+>>> f = IDLicensePlateField(required=False)
  129
+>>> f.clean('')
  130
+u''
  131
+>>> f.clean(' b 1234  ab ')
  132
+u'B 1234 AB'
  133
+>>> f.clean('B 1234 ABC')
  134
+u'B 1234 ABC'
  135
+>>> f.clean('A 12')
  136
+u'A 12'
  137
+>>> f.clean('DK 12345 12')
  138
+u'DK 12345 12'
  139
+>>> f.clean('RI 10')
  140
+u'RI 10'
  141
+>>> f.clean('CD 12 12')
  142
+u'CD 12 12'
  143
+>>> f.clean('CD 10 12')
  144
+Traceback (most recent call last):
  145
+    ...
  146
+ValidationError: [u'Enter a valid vehicle license plate number']
  147
+>>> f.clean('CD 1234 12')
  148
+Traceback (most recent call last):
  149
+    ...
  150
+ValidationError: [u'Enter a valid vehicle license plate number']
  151
+>>> f.clean('RI 10 AB')
  152
+Traceback (most recent call last):
  153
+    ...
  154
+ValidationError: [u'Enter a valid vehicle license plate number']
  155
+>>> f.clean('B 12345 01')
  156
+Traceback (most recent call last):
  157
+    ...
  158
+ValidationError: [u'Enter a valid vehicle license plate number']
  159
+>>> f.clean('N 1234 12')
  160
+Traceback (most recent call last):
  161
+    ...
  162
+ValidationError: [u'Enter a valid vehicle license plate number']
  163
+>>> f.clean('A 12 XYZ')
  164
+Traceback (most recent call last):
  165
+    ...
  166
+ValidationError: [u'Enter a valid vehicle license plate number']
  167
+>>> f.clean('Q 1234 AB')
  168
+Traceback (most recent call last):
  169
+    ...
  170
+ValidationError: [u'Enter a valid vehicle license plate number']
  171
+>>> f.clean('foo')
  172
+Traceback (most recent call last):
  173
+    ...
  174
+ValidationError: [u'Enter a valid vehicle license plate number']
  175
+"""
2  tests/regressiontests/forms/tests.py
@@ -15,6 +15,7 @@
15 15
 from localflavor.fi import tests as localflavor_fi_tests
16 16
 from localflavor.fr import tests as localflavor_fr_tests
17 17
 from localflavor.generic import tests as localflavor_generic_tests
  18
+from localflavor.id import tests as localflavor_id_tests
18 19
 from localflavor.ie import tests as localflavor_ie_tests
19 20
 from localflavor.is_ import tests as localflavor_is_tests
20 21
 from localflavor.it import tests as localflavor_it_tests
@@ -54,6 +55,7 @@
54 55
     'localflavor_fi_tests': localflavor_fi_tests,
55 56
     'localflavor_fr_tests': localflavor_fr_tests,
56 57
     'localflavor_generic_tests': localflavor_generic_tests,
  58
+    'localflavor_id_tests': localflavor_id_tests,
57 59
     'localflavor_ie_tests': localflavor_ie_tests,
58 60
     'localflavor_is_tests': localflavor_is_tests,
59 61
     'localflavor_it_tests': localflavor_it_tests,

0 notes on commit e0dc28d

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