Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #4036 -- Added Spanish localflavor. Thanks, ricardojbarrios@gma…

…il.com and

oggie_rob.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@6555 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit aac5555f2fb333d958e838274fd18cf3ac89d914 1 parent bece031
Malcolm Tredinnick authored October 20, 2007
1  AUTHORS
@@ -257,6 +257,7 @@ answer newbie questions, and generally made Django that much better:
257 257
     Brian Ray <http://brianray.chipy.org/>
258 258
     remco@diji.biz
259 259
     rhettg@gmail.com
  260
+    ricardojbarrios@gmail.com
260 261
     Matt Riggott
261 262
     Henrique Romano <onaiort@gmail.com>
262 263
     Armin Ronacher
58  django/contrib/localflavor/es/es_provinces.py
... ...
@@ -0,0 +1,58 @@
  1
+# -*- coding: utf-8 -*-
  2
+from django.utils.translation import ugettext_lazy as _
  3
+
  4
+PROVINCE_CHOICES = (
  5
+    ('01', _('Arava')),
  6
+    ('02', _('Albacete')),
  7
+    ('03', _('Alacant')),
  8
+    ('04', _('Almeria')),
  9
+    ('05', _('Avila')),
  10
+    ('06', _('Badajoz')),
  11
+    ('07', _('Illes Balears')),
  12
+    ('08', _('Barcelona')),
  13
+    ('09', _('Burgos')),
  14
+    ('10', _('Caceres')),
  15
+    ('11', _('Cadiz')),
  16
+    ('12', _('Castello')),
  17
+    ('13', _('Ciudad Real')),
  18
+    ('14', _('Cordoba')),
  19
+    ('15', _('A Coruna')),
  20
+    ('16', _('Cuenca')),
  21
+    ('17', _('Girona')),
  22
+    ('18', _('Granada')),
  23
+    ('19', _('Guadalajara')),
  24
+    ('20', _('Guipuzkoa')),
  25
+    ('21', _('Huelva')),
  26
+    ('22', _('Huesca')),
  27
+    ('23', _('Jaen')),
  28
+    ('24', _('Leon')),
  29
+    ('25', _('Lleida')),
  30
+    ('26', _('La Rioja')),
  31
+    ('27', _('Lugo')),
  32
+    ('28', _('Madrid')),
  33
+    ('29', _('Malaga')),
  34
+    ('30', _('Murcia')),
  35
+    ('31', _('Navarre')),
  36
+    ('32', _('Ourense')),
  37
+    ('33', _('Asturias')),
  38
+    ('34', _('Palencia')),
  39
+    ('35', _('Las Palmas')),
  40
+    ('36', _('Pontevedra')),
  41
+    ('37', _('Salamanca')),
  42
+    ('38', _('Santa Cruz de Tenerife')),
  43
+    ('39', _('Cantabria')),
  44
+    ('40', _('Segovia')),
  45
+    ('41', _('Seville')),
  46
+    ('42', _('Soria')),
  47
+    ('43', _('Tarragona')),
  48
+    ('44', _('Teruel')),
  49
+    ('45', _('Toledo')),
  50
+    ('46', _('Valencia')),
  51
+    ('47', _('Valladolid')),
  52
+    ('48', _('Bizkaia')),
  53
+    ('49', _('Zamora')),
  54
+    ('50', _('Zaragoza')),
  55
+    ('51', _('Ceuta')),
  56
+    ('52', _('Melilla')),
  57
+)
  58
+
23  django/contrib/localflavor/es/es_regions.py
... ...
@@ -0,0 +1,23 @@
  1
+# -*- coding: utf-8 -*-
  2
+from django.utils.translation import ugettext_lazy as _
  3
+
  4
+REGION_CHOICES = (
  5
+    ('AN', _('Andalusia')),
  6
+    ('AR', _('Aragon')),
  7
+    ('O', _('Principality of Asturias')),
  8
+    ('IB', _('Balearic Islands')),
  9
+    ('PV', _('Basque Country')),
  10
+    ('CN', _('Canary Islands')),
  11
+    ('S', _('Cantabria')),
  12
+    ('CM', _('Castile-La Mancha')),
  13
+    ('CL', _('Castile and Leon')),
  14
+    ('CT', _('Catalonia')),
  15
+    ('EX', _('Extremadura')),
  16
+    ('GA', _('Galicia')),
  17
+    ('LO', _('La Rioja')),
  18
+    ('M', _('Madrid')),
  19
+    ('MU', _('Region of Murcia')),
  20
+    ('NA', _('Foral Community of Navarre')),
  21
+    ('VC', _('Valencian Community')),
  22
+)
  23
+
173  django/contrib/localflavor/es/forms.py
... ...
@@ -0,0 +1,173 @@
  1
+# -*- coding: utf-8 -*-
  2
+"""
  3
+Spanish-specific Form helpers
  4
+"""
  5
+
  6
+from django.newforms import ValidationError
  7
+from django.newforms.fields import RegexField, Select, EMPTY_VALUES
  8
+from django.utils.translation import ugettext as _
  9
+import re
  10
+
  11
+class ESPostalCodeField(RegexField):
  12
+    """
  13
+    A form field that validates its input as a spanish postal code.
  14
+
  15
+    Spanish postal code is a five digits string, with two first digits
  16
+    between 01 and 52, assigned to provinces code.
  17
+    """
  18
+    def __init__(self, *args, **kwargs):
  19
+        super(ESPostalCodeField, self).__init__(
  20
+                r'^(0[1-9]|[1-4][0-9]|5[0-2])\d{3}$',
  21
+                max_length=None, min_length=None,
  22
+                error_message=_('Enter a valid postal code in the range and format 01XXX - 52XXX.'),
  23
+                *args, **kwargs)
  24
+
  25
+class ESPhoneNumberField(RegexField):
  26
+    """
  27
+    A form field that validates its input as a Spanish phone number.
  28
+    Information numbers are ommited.
  29
+
  30
+    Spanish phone numbers are nine digit numbers, where first digit is 6 (for
  31
+    cell phones), 8 (for special phones), or 9 (for landlines and special
  32
+    phones)
  33
+
  34
+    TODO: accept and strip characters like dot, hyphen... in phone number
  35
+    """
  36
+    def __init__(self, *args, **kwargs):
  37
+        super(ESPhoneNumberField, self).__init__(r'^(6|8|9)\d{8}$',
  38
+                max_length=None, min_length=None,
  39
+                error_message=_('Enter a valid phone number in one of the formats 6XXXXXXXX, 8XXXXXXXX or 9XXXXXXXX.'),
  40
+                *args, **kwargs)
  41
+
  42
+class ESIdentityCardNumberField(RegexField):
  43
+    """
  44
+    Spanish NIF/NIE/CIF (Fiscal Identification Number) code.
  45
+
  46
+    Validates three diferent formats:
  47
+
  48
+        NIF (individuals): 12345678A
  49
+        CIF (companies): A12345678
  50
+        NIE (foreigners): X12345678A
  51
+
  52
+    according to a couple of simple checksum algorithms.
  53
+
  54
+    Value can include a space or hyphen separator between number and letters.
  55
+    Number length is not checked for NIF (or NIE), old values start with a 1,
  56
+    and future values can contain digits greater than 8. The CIF control digit
  57
+    can be a number or a letter depending on company type. Algorithm is not
  58
+    public, and different authors have different opinions on which ones allows
  59
+    letters, so both validations are assumed true for all types.
  60
+    """
  61
+    def __init__(self, only_nif=False, *args, **kwargs):
  62
+        self.only_nif = only_nif
  63
+        self.nif_control = 'TRWAGMYFPDXBNJZSQVHLCKE'
  64
+        self.cif_control = 'JABCDEFGHI'
  65
+        self.cif_types = 'ABCDEFGHKLMNPQS'
  66
+        self.nie_types = 'XT'
  67
+        if self.only_nif:
  68
+            self.id_types = 'NIF or NIE'
  69
+        else:
  70
+            self.id_types = 'NIF, NIE, or CIF'
  71
+        super(ESIdentityCardNumberField, self).__init__(r'^([%s]?)[ -]?(\d+)[ -]?([%s]?)$' % (self.cif_types + self.nie_types + self.cif_types.lower() + self.nie_types.lower(), self.nif_control + self.nif_control.lower()),
  72
+                max_length=None, min_length=None,
  73
+                error_message=_('Please enter a valid %s.' % self.id_types),
  74
+                *args, **kwargs)
  75
+
  76
+    def clean(self, value):
  77
+        super(ESIdentityCardNumberField, self).clean(value)
  78
+        if value in EMPTY_VALUES:
  79
+            return u''
  80
+        nif_get_checksum = lambda d: self.nif_control[int(d)%23]
  81
+
  82
+        value = value.upper().replace(' ', '').replace('-', '')
  83
+        m = re.match(r'^([%s]?)[ -]?(\d+)[ -]?([%s]?)$' % (self.cif_types + self.nie_types, self.nif_control), value)
  84
+        letter1, number, letter2 = m.groups()
  85
+
  86
+        if not letter1 and letter2:
  87
+            # NIF
  88
+            if letter2 == nif_get_checksum(number):
  89
+                return value
  90
+            else:
  91
+                raise ValidationError, _('Invalid checksum for NIF.')
  92
+        elif letter1 in self.nie_types and letter2:
  93
+            # NIE
  94
+            if letter2 == nif_get_checksum(number):
  95
+                return value
  96
+            else:
  97
+                raise ValidationError, _('Invalid checksum for NIE.')
  98
+        elif not self.only_nif and letter1 in self.cif_types and len(number) in [7, 8]:
  99
+            # CIF
  100
+            if not letter2:
  101
+                number, letter2 = number[:-1], int(number[-1])
  102
+            checksum = cif_get_checksum(number)
  103
+            if letter2 in [checksum, self.cif_control[checksum]]:
  104
+                return value
  105
+            else:
  106
+                raise ValidationError, _('Invalid checksum for CIF.')
  107
+        else:
  108
+            raise ValidationError, _('Please enter a valid %s.' % self.id_types)
  109
+
  110
+class ESCCCField(RegexField):
  111
+    """
  112
+    A form field that validates its input as a Spanish bank account or CCC
  113
+    (Codigo Cuenta Cliente).
  114
+
  115
+        Spanish CCC is in format EEEE-OOOO-CC-AAAAAAAAAA where:
  116
+
  117
+            E = entity
  118
+            O = office
  119
+            C = checksum
  120
+            A = account
  121
+
  122
+        It's also valid to use a space as delimiter, or to use no delimiter.
  123
+
  124
+        First checksum digit validates entity and office, and last one
  125
+        validates account. Validation is done multiplying every digit of 10
  126
+        digit value (with leading 0 if necessary) by number in its position in
  127
+        string 1, 2, 4, 8, 5, 10, 9, 7, 3, 6. Sum resulting numbers and extract
  128
+        it from 11.  Result is checksum except when 10 then is 1, or when 11
  129
+        then is 0.
  130
+
  131
+        TODO: allow IBAN validation too
  132
+    """
  133
+    def __init__(self, *args, **kwargs):
  134
+        super(ESCCCField, self).__init__(r'^\d{4}[ -]?\d{4}[ -]?\d{2}[ -]?\d{10}$',
  135
+            max_length=None, min_length=None,
  136
+            error_message=_('Please enter a valid bank account number in format XXXX-XXXX-XX-XXXXXXXXXX.'),
  137
+            *args, **kwargs)
  138
+
  139
+    def clean(self, value):
  140
+        super(ESCCCField, self).clean(value)
  141
+        if value in EMPTY_VALUES:
  142
+            return u''
  143
+        control_str = [1, 2, 4, 8, 5, 10, 9, 7, 3, 6]
  144
+        m = re.match(r'^(\d{4})[ -]?(\d{4})[ -]?(\d{2})[ -]?(\d{10})$', value)
  145
+        entity, office, checksum, account = m.groups()
  146
+        get_checksum = lambda d: str(11 - sum([int(digit) * int(control) for digit, control in zip(d, control_str)]) % 11).replace('10', '1').replace('11', '0')
  147
+        if get_checksum('00' + entity + office) + get_checksum(account) == checksum:
  148
+            return value
  149
+        else:
  150
+            raise ValidationError, _('Invalid checksum for bank account number.')
  151
+
  152
+class ESRegionSelect(Select):
  153
+    """
  154
+    A Select widget that uses a list of spanish regions as its choices.
  155
+    """
  156
+    def __init__(self, attrs=None):
  157
+        from es_regions import REGION_CHOICES
  158
+        super(ESRegionSelect, self).__init__(attrs, choices=REGION_CHOICES)
  159
+
  160
+class ESProvinceSelect(Select):
  161
+    """
  162
+    A Select widget that uses a list of spanish provinces as its choices.
  163
+    """
  164
+    def __init__(self, attrs=None):
  165
+        from es_provinces import PROVINCE_CHOICES
  166
+        super(ESProvinceSelect, self).__init__(attrs, choices=PROVINCE_CHOICES)
  167
+
  168
+
  169
+def cif_get_checksum(number):
  170
+    s1 = sum([int(digit) for pos, digit in enumerate(number) if int(pos) % 2])
  171
+    s2 = sum([sum([int(unit) for unit in str(int(digit) * 2)]) for pos, digit in enumerate(number) if not int(pos) % 2])
  172
+    return 10 - ((s1 + s2) % 10)
  173
+
0  localflavor/es/__init__.py b/django/contrib/localflavor/es/__init__.py
No changes.
343  tests/regressiontests/forms/localflavor/es.py
... ...
@@ -0,0 +1,343 @@
  1
+# -*- coding: utf-8 -*-
  2
+# Tests for the contrib/localflavor/ ES form fields.
  3
+
  4
+tests = r"""
  5
+# ESPostalCodeField ##############################################################
  6
+
  7
+ESPostalCodeField validates that data is a five-digit spanish postal code.
  8
+>>> from django.contrib.localflavor.es.forms import ESPostalCodeField
  9
+>>> f = ESPostalCodeField()
  10
+>>> f.clean('08028')
  11
+u'08028'
  12
+>>> f.clean('28080')
  13
+u'28080'
  14
+>>> f.clean('53001')
  15
+Traceback (most recent call last):
  16
+...
  17
+ValidationError: [u'Enter a valid postal code in the range and format 01XXX - 52XXX.']
  18
+>>> f.clean('0801')
  19
+Traceback (most recent call last):
  20
+...
  21
+ValidationError: [u'Enter a valid postal code in the range and format 01XXX - 52XXX.']
  22
+>>> f.clean('080001')
  23
+Traceback (most recent call last):
  24
+...
  25
+ValidationError: [u'Enter a valid postal code in the range and format 01XXX - 52XXX.']
  26
+>>> f.clean('00999')
  27
+Traceback (most recent call last):
  28
+...
  29
+ValidationError: [u'Enter a valid postal code in the range and format 01XXX - 52XXX.']
  30
+>>> f.clean('08 01')
  31
+Traceback (most recent call last):
  32
+...
  33
+ValidationError: [u'Enter a valid postal code in the range and format 01XXX - 52XXX.']
  34
+>>> f.clean('08A01')
  35
+Traceback (most recent call last):
  36
+...
  37
+ValidationError: [u'Enter a valid postal code in the range and format 01XXX - 52XXX.']
  38
+>>> f.clean('')
  39
+Traceback (most recent call last):
  40
+...
  41
+ValidationError: [u'This field is required.']
  42
+
  43
+>>> f = ESPostalCodeField(required=False)
  44
+>>> f.clean('08028')
  45
+u'08028'
  46
+>>> f.clean('28080')
  47
+u'28080'
  48
+>>> f.clean('53001')
  49
+Traceback (most recent call last):
  50
+...
  51
+ValidationError: [u'Enter a valid postal code in the range and format 01XXX - 52XXX.']
  52
+>>> f.clean('0801')
  53
+Traceback (most recent call last):
  54
+...
  55
+ValidationError: [u'Enter a valid postal code in the range and format 01XXX - 52XXX.']
  56
+>>> f.clean('080001')
  57
+Traceback (most recent call last):
  58
+...
  59
+ValidationError: [u'Enter a valid postal code in the range and format 01XXX - 52XXX.']
  60
+>>> f.clean('00999')
  61
+Traceback (most recent call last):
  62
+...
  63
+ValidationError: [u'Enter a valid postal code in the range and format 01XXX - 52XXX.']
  64
+>>> f.clean('08 01')
  65
+Traceback (most recent call last):
  66
+...
  67
+ValidationError: [u'Enter a valid postal code in the range and format 01XXX - 52XXX.']
  68
+>>> f.clean('08A01')
  69
+Traceback (most recent call last):
  70
+...
  71
+ValidationError: [u'Enter a valid postal code in the range and format 01XXX - 52XXX.']
  72
+>>> f.clean('')
  73
+u''
  74
+
  75
+# ESPhoneNumberField ##############################################################
  76
+
  77
+ESPhoneNumberField validates that data is a nine-digit spanish phone number.
  78
+>>> from django.contrib.localflavor.es.forms import ESPhoneNumberField
  79
+>>> f = ESPhoneNumberField()
  80
+>>> f.clean('650010101')
  81
+u'650010101'
  82
+>>> f.clean('931234567')
  83
+u'931234567'
  84
+>>> f.clean('800123123')
  85
+u'800123123'
  86
+>>> f.clean('555555555')
  87
+Traceback (most recent call last):
  88
+...
  89
+ValidationError: [u'Enter a valid phone number in one of the formats 6XXXXXXXX, 8XXXXXXXX or 9XXXXXXXX.']
  90
+>>> f.clean('789789789')
  91
+Traceback (most recent call last):
  92
+...
  93
+ValidationError: [u'Enter a valid phone number in one of the formats 6XXXXXXXX, 8XXXXXXXX or 9XXXXXXXX.']
  94
+>>> f.clean('99123123')
  95
+Traceback (most recent call last):
  96
+...
  97
+ValidationError: [u'Enter a valid phone number in one of the formats 6XXXXXXXX, 8XXXXXXXX or 9XXXXXXXX.']
  98
+>>> f.clean('9999123123')
  99
+Traceback (most recent call last):
  100
+...
  101
+ValidationError: [u'Enter a valid phone number in one of the formats 6XXXXXXXX, 8XXXXXXXX or 9XXXXXXXX.']
  102
+>>> f.clean('')
  103
+Traceback (most recent call last):
  104
+...
  105
+ValidationError: [u'This field is required.']
  106
+
  107
+>>> f = ESPhoneNumberField(required=False)
  108
+>>> f.clean('650010101')
  109
+u'650010101'
  110
+>>> f.clean('931234567')
  111
+u'931234567'
  112
+>>> f.clean('800123123')
  113
+u'800123123'
  114
+>>> f.clean('555555555')
  115
+Traceback (most recent call last):
  116
+...
  117
+ValidationError: [u'Enter a valid phone number in one of the formats 6XXXXXXXX, 8XXXXXXXX or 9XXXXXXXX.']
  118
+>>> f.clean('789789789')
  119
+Traceback (most recent call last):
  120
+...
  121
+ValidationError: [u'Enter a valid phone number in one of the formats 6XXXXXXXX, 8XXXXXXXX or 9XXXXXXXX.']
  122
+>>> f.clean('99123123')
  123
+Traceback (most recent call last):
  124
+...
  125
+ValidationError: [u'Enter a valid phone number in one of the formats 6XXXXXXXX, 8XXXXXXXX or 9XXXXXXXX.']
  126
+>>> f.clean('9999123123')
  127
+Traceback (most recent call last):
  128
+...
  129
+ValidationError: [u'Enter a valid phone number in one of the formats 6XXXXXXXX, 8XXXXXXXX or 9XXXXXXXX.']
  130
+>>> f.clean('')
  131
+u''
  132
+
  133
+# ESIdentityCardNumberField ##############################################################
  134
+
  135
+ESIdentityCardNumberField validates that data is a identification spanish code for companies or individuals (CIF, NIF or NIE).
  136
+>>> from django.contrib.localflavor.es.forms import ESIdentityCardNumberField
  137
+>>> f = ESIdentityCardNumberField()
  138
+>>> f.clean('78699688J')
  139
+'78699688J'
  140
+>>> f.clean('78699688-J')
  141
+'78699688J'
  142
+>>> f.clean('78699688 J')
  143
+'78699688J'
  144
+>>> f.clean('78699688 j')
  145
+'78699688J'
  146
+>>> f.clean('78699688T')
  147
+Traceback (most recent call last):
  148
+...
  149
+ValidationError: [u'Invalid checksum for NIF.']
  150
+>>> f.clean('X0901797J')
  151
+'X0901797J'
  152
+>>> f.clean('X-6124387-Q')
  153
+'X6124387Q'
  154
+>>> f.clean('X 0012953 G')
  155
+'X0012953G'
  156
+>>> f.clean('x-3287690-r')
  157
+'X3287690R'
  158
+>>> f.clean('t-03287690r')
  159
+'T03287690R'
  160
+>>> f.clean('X-03287690')
  161
+Traceback (most recent call last):
  162
+...
  163
+ValidationError: [u'Please enter a valid NIF, NIE, or CIF.']
  164
+>>> f.clean('X-03287690-T')
  165
+Traceback (most recent call last):
  166
+...
  167
+ValidationError: [u'Invalid checksum for NIE.']
  168
+>>> f.clean('B38790911')
  169
+'B38790911'
  170
+>>> f.clean('B-3879091A')
  171
+'B3879091A'
  172
+>>> f.clean('B 38790917')
  173
+Traceback (most recent call last):
  174
+...
  175
+ValidationError: [u'Invalid checksum for CIF.']
  176
+>>> f.clean('B 38790911')
  177
+'B38790911'
  178
+>>> f.clean('P-3900800-H')
  179
+'P3900800H'
  180
+>>> f.clean('P 39008008')
  181
+'P39008008'
  182
+>>> f.clean('C-28795565')
  183
+'C28795565'
  184
+>>> f.clean('C 2879556E')
  185
+'C2879556E'
  186
+>>> f.clean('C28795567')
  187
+Traceback (most recent call last):
  188
+...
  189
+ValidationError: [u'Invalid checksum for CIF.']
  190
+>>> f.clean('I38790911')
  191
+Traceback (most recent call last):
  192
+...
  193
+ValidationError: [u'Please enter a valid NIF, NIE, or CIF.']
  194
+>>> f.clean('78699688-2')
  195
+Traceback (most recent call last):
  196
+...
  197
+ValidationError: [u'Please enter a valid NIF, NIE, or CIF.']
  198
+>>> f.clean('')
  199
+Traceback (most recent call last):
  200
+...
  201
+ValidationError: [u'This field is required.']
  202
+
  203
+>>> f = ESIdentityCardNumberField(required=False)
  204
+>>> f.clean('78699688J')
  205
+'78699688J'
  206
+>>> f.clean('78699688-J')
  207
+'78699688J'
  208
+>>> f.clean('78699688 J')
  209
+'78699688J'
  210
+>>> f.clean('78699688 j')
  211
+'78699688J'
  212
+>>> f.clean('78699688T')
  213
+Traceback (most recent call last):
  214
+...
  215
+ValidationError: [u'Invalid checksum for NIF.']
  216
+>>> f.clean('X0901797J')
  217
+'X0901797J'
  218
+>>> f.clean('X-6124387-Q')
  219
+'X6124387Q'
  220
+>>> f.clean('X 0012953 G')
  221
+'X0012953G'
  222
+>>> f.clean('x-3287690-r')
  223
+'X3287690R'
  224
+>>> f.clean('t-03287690r')
  225
+'T03287690R'
  226
+>>> f.clean('X-03287690')
  227
+Traceback (most recent call last):
  228
+...
  229
+ValidationError: [u'Please enter a valid NIF, NIE, or CIF.']
  230
+>>> f.clean('X-03287690-T')
  231
+Traceback (most recent call last):
  232
+...
  233
+ValidationError: [u'Invalid checksum for NIE.']
  234
+>>> f.clean('B38790911')
  235
+'B38790911'
  236
+>>> f.clean('B-3879091A')
  237
+'B3879091A'
  238
+>>> f.clean('B 38790917')
  239
+Traceback (most recent call last):
  240
+...
  241
+ValidationError: [u'Invalid checksum for CIF.']
  242
+>>> f.clean('B 38790911')
  243
+'B38790911'
  244
+>>> f.clean('P-3900800-H')
  245
+'P3900800H'
  246
+>>> f.clean('P 39008008')
  247
+'P39008008'
  248
+>>> f.clean('C-28795565')
  249
+'C28795565'
  250
+>>> f.clean('C 2879556E')
  251
+'C2879556E'
  252
+>>> f.clean('C28795567')
  253
+Traceback (most recent call last):
  254
+...
  255
+ValidationError: [u'Invalid checksum for CIF.']
  256
+>>> f.clean('I38790911')
  257
+Traceback (most recent call last):
  258
+...
  259
+ValidationError: [u'Please enter a valid NIF, NIE, or CIF.']
  260
+>>> f.clean('78699688-2')
  261
+Traceback (most recent call last):
  262
+...
  263
+ValidationError: [u'Please enter a valid NIF, NIE, or CIF.']
  264
+>>> f.clean('')
  265
+u''
  266
+
  267
+# ESCCCField ##############################################################
  268
+
  269
+ESCCCField validates that data is a spanish bank account number (codigo cuenta cliente).
  270
+
  271
+>>> from django.contrib.localflavor.es.forms import ESCCCField
  272
+>>> f = ESCCCField()
  273
+>>> f.clean('20770338793100254321')
  274
+'20770338793100254321'
  275
+>>> f.clean('2077 0338 79 3100254321')
  276
+'2077 0338 79 3100254321'
  277
+>>> f.clean('2077-0338-79-3100254321')
  278
+'2077-0338-79-3100254321'
  279
+>>> f.clean('2077.0338.79.3100254321')
  280
+Traceback (most recent call last):
  281
+...
  282
+ValidationError: [u'Please enter a valid bank account number in format XXXX-XXXX-XX-XXXXXXXXXX.']
  283
+>>> f.clean('2077-0338-78-3100254321')
  284
+Traceback (most recent call last):
  285
+...
  286
+ValidationError: [u'Invalid checksum for bank account number.']
  287
+>>> f.clean('2077-0338-89-3100254321')
  288
+Traceback (most recent call last):
  289
+...
  290
+ValidationError: [u'Invalid checksum for bank account number.']
  291
+>>> f.clean('2077-03-3879-3100254321')
  292
+Traceback (most recent call last):
  293
+...
  294
+ValidationError: [u'Please enter a valid bank account number in format XXXX-XXXX-XX-XXXXXXXXXX.']
  295
+>>> f.clean('')
  296
+Traceback (most recent call last):
  297
+...
  298
+ValidationError: [u'This field is required.']
  299
+
  300
+>>> f = ESCCCField(required=False)
  301
+>>> f.clean('20770338793100254321')
  302
+'20770338793100254321'
  303
+>>> f.clean('2077 0338 79 3100254321')
  304
+'2077 0338 79 3100254321'
  305
+>>> f.clean('2077-0338-79-3100254321')
  306
+'2077-0338-79-3100254321'
  307
+>>> f.clean('2077.0338.79.3100254321')
  308
+Traceback (most recent call last):
  309
+...
  310
+ValidationError: [u'Please enter a valid bank account number in format XXXX-XXXX-XX-XXXXXXXXXX.']
  311
+>>> f.clean('2077-0338-78-3100254321')
  312
+Traceback (most recent call last):
  313
+...
  314
+ValidationError: [u'Invalid checksum for bank account number.']
  315
+>>> f.clean('2077-0338-89-3100254321')
  316
+Traceback (most recent call last):
  317
+...
  318
+ValidationError: [u'Invalid checksum for bank account number.']
  319
+>>> f.clean('2077-03-3879-3100254321')
  320
+Traceback (most recent call last):
  321
+...
  322
+ValidationError: [u'Please enter a valid bank account number in format XXXX-XXXX-XX-XXXXXXXXXX.']
  323
+>>> f.clean('')
  324
+u''
  325
+
  326
+# ESRegionSelect ##############################################################
  327
+
  328
+ESRegionSelect is a Select widget that uses a list of Spain regions as its choices.
  329
+>>> from django.contrib.localflavor.es.forms import ESRegionSelect
  330
+>>> w = ESRegionSelect()
  331
+>>> w.render('regions', 'CT')
  332
+u'<select name="regions">\n<option value="AN">Andalusia</option>\n<option value="AR">Aragon</option>\n<option value="O">Principality of Asturias</option>\n<option value="IB">Balearic Islands</option>\n<option value="PV">Basque Country</option>\n<option value="CN">Canary Islands</option>\n<option value="S">Cantabria</option>\n<option value="CM">Castile-La Mancha</option>\n<option value="CL">Castile and Leon</option>\n<option value="CT" selected="selected">Catalonia</option>\n<option value="EX">Extremadura</option>\n<option value="GA">Galicia</option>\n<option value="LO">La Rioja</option>\n<option value="M">Madrid</option>\n<option value="MU">Region of Murcia</option>\n<option value="NA">Foral Community of Navarre</option>\n<option value="VC">Valencian Community</option>\n</select>'
  333
+
  334
+# ESProvincenSelect ##############################################################
  335
+
  336
+ESProvinceSelect is a Select widget that uses a list of Spain provinces as its choices.
  337
+>>> from django.contrib.localflavor.es.forms import ESProvinceSelect
  338
+>>> w = ESProvinceSelect()
  339
+>>> w.render('provinces', '08')
  340
+u'<select name="provinces">\n<option value="01">Arava</option>\n<option value="02">Albacete</option>\n<option value="03">Alacant</option>\n<option value="04">Almeria</option>\n<option value="05">Avila</option>\n<option value="06">Badajoz</option>\n<option value="07">Illes Balears</option>\n<option value="08" selected="selected">Barcelona</option>\n<option value="09">Burgos</option>\n<option value="10">Caceres</option>\n<option value="11">Cadiz</option>\n<option value="12">Castello</option>\n<option value="13">Ciudad Real</option>\n<option value="14">Cordoba</option>\n<option value="15">A Coruna</option>\n<option value="16">Cuenca</option>\n<option value="17">Girona</option>\n<option value="18">Granada</option>\n<option value="19">Guadalajara</option>\n<option value="20">Guipuzkoa</option>\n<option value="21">Huelva</option>\n<option value="22">Huesca</option>\n<option value="23">Jaen</option>\n<option value="24">Leon</option>\n<option value="25">Lleida</option>\n<option value="26">La Rioja</option>\n<option value="27">Lugo</option>\n<option value="28">Madrid</option>\n<option value="29">Malaga</option>\n<option value="30">Murcia</option>\n<option value="31">Navarre</option>\n<option value="32">Ourense</option>\n<option value="33">Asturias</option>\n<option value="34">Palencia</option>\n<option value="35">Las Palmas</option>\n<option value="36">Pontevedra</option>\n<option value="37">Salamanca</option>\n<option value="38">Santa Cruz de Tenerife</option>\n<option value="39">Cantabria</option>\n<option value="40">Segovia</option>\n<option value="41">Seville</option>\n<option value="42">Soria</option>\n<option value="43">Tarragona</option>\n<option value="44">Teruel</option>\n<option value="45">Toledo</option>\n<option value="46">Valencia</option>\n<option value="47">Valladolid</option>\n<option value="48">Bizkaia</option>\n<option value="49">Zamora</option>\n<option value="50">Zaragoza</option>\n<option value="51">Ceuta</option>\n<option value="52">Melilla</option>\n</select>'
  341
+
  342
+"""
  343
+
2  tests/regressiontests/forms/tests.py
@@ -9,6 +9,7 @@
9 9
 from localflavor.ch import tests as localflavor_ch_tests
10 10
 from localflavor.cl import tests as localflavor_cl_tests
11 11
 from localflavor.de import tests as localflavor_de_tests
  12
+from localflavor.es import tests as localflavor_es_tests
12 13
 from localflavor.fi import tests as localflavor_fi_tests
13 14
 from localflavor.fr import tests as localflavor_fr_tests
14 15
 from localflavor.generic import tests as localflavor_generic_tests
@@ -35,6 +36,7 @@
35 36
     'localflavor_ch_tests': localflavor_ch_tests,
36 37
     'localflavor_cl_tests': localflavor_cl_tests,
37 38
     'localflavor_de_tests': localflavor_de_tests,
  39
+    'localflavor_es_tests': localflavor_es_tests,
38 40
     'localflavor_fi_tests': localflavor_fi_tests,
39 41
     'localflavor_fr_tests': localflavor_fr_tests,
40 42
     'localflavor_generic_tests': localflavor_generic_tests,

0 notes on commit aac5555

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