Fixed #4036 -- Added Spanish localflavor. Thanks, ricardojbarrios@gmail.com and
oggie_rob. git-svn-id: http://code.djangoproject.com/svn/django/trunk@6555 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
bece031772
commit
aac5555f2f
1
AUTHORS
1
AUTHORS
|
@ -257,6 +257,7 @@ answer newbie questions, and generally made Django that much better:
|
||||||
Brian Ray <http://brianray.chipy.org/>
|
Brian Ray <http://brianray.chipy.org/>
|
||||||
remco@diji.biz
|
remco@diji.biz
|
||||||
rhettg@gmail.com
|
rhettg@gmail.com
|
||||||
|
ricardojbarrios@gmail.com
|
||||||
Matt Riggott
|
Matt Riggott
|
||||||
Henrique Romano <onaiort@gmail.com>
|
Henrique Romano <onaiort@gmail.com>
|
||||||
Armin Ronacher
|
Armin Ronacher
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
PROVINCE_CHOICES = (
|
||||||
|
('01', _('Arava')),
|
||||||
|
('02', _('Albacete')),
|
||||||
|
('03', _('Alacant')),
|
||||||
|
('04', _('Almeria')),
|
||||||
|
('05', _('Avila')),
|
||||||
|
('06', _('Badajoz')),
|
||||||
|
('07', _('Illes Balears')),
|
||||||
|
('08', _('Barcelona')),
|
||||||
|
('09', _('Burgos')),
|
||||||
|
('10', _('Caceres')),
|
||||||
|
('11', _('Cadiz')),
|
||||||
|
('12', _('Castello')),
|
||||||
|
('13', _('Ciudad Real')),
|
||||||
|
('14', _('Cordoba')),
|
||||||
|
('15', _('A Coruna')),
|
||||||
|
('16', _('Cuenca')),
|
||||||
|
('17', _('Girona')),
|
||||||
|
('18', _('Granada')),
|
||||||
|
('19', _('Guadalajara')),
|
||||||
|
('20', _('Guipuzkoa')),
|
||||||
|
('21', _('Huelva')),
|
||||||
|
('22', _('Huesca')),
|
||||||
|
('23', _('Jaen')),
|
||||||
|
('24', _('Leon')),
|
||||||
|
('25', _('Lleida')),
|
||||||
|
('26', _('La Rioja')),
|
||||||
|
('27', _('Lugo')),
|
||||||
|
('28', _('Madrid')),
|
||||||
|
('29', _('Malaga')),
|
||||||
|
('30', _('Murcia')),
|
||||||
|
('31', _('Navarre')),
|
||||||
|
('32', _('Ourense')),
|
||||||
|
('33', _('Asturias')),
|
||||||
|
('34', _('Palencia')),
|
||||||
|
('35', _('Las Palmas')),
|
||||||
|
('36', _('Pontevedra')),
|
||||||
|
('37', _('Salamanca')),
|
||||||
|
('38', _('Santa Cruz de Tenerife')),
|
||||||
|
('39', _('Cantabria')),
|
||||||
|
('40', _('Segovia')),
|
||||||
|
('41', _('Seville')),
|
||||||
|
('42', _('Soria')),
|
||||||
|
('43', _('Tarragona')),
|
||||||
|
('44', _('Teruel')),
|
||||||
|
('45', _('Toledo')),
|
||||||
|
('46', _('Valencia')),
|
||||||
|
('47', _('Valladolid')),
|
||||||
|
('48', _('Bizkaia')),
|
||||||
|
('49', _('Zamora')),
|
||||||
|
('50', _('Zaragoza')),
|
||||||
|
('51', _('Ceuta')),
|
||||||
|
('52', _('Melilla')),
|
||||||
|
)
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
REGION_CHOICES = (
|
||||||
|
('AN', _('Andalusia')),
|
||||||
|
('AR', _('Aragon')),
|
||||||
|
('O', _('Principality of Asturias')),
|
||||||
|
('IB', _('Balearic Islands')),
|
||||||
|
('PV', _('Basque Country')),
|
||||||
|
('CN', _('Canary Islands')),
|
||||||
|
('S', _('Cantabria')),
|
||||||
|
('CM', _('Castile-La Mancha')),
|
||||||
|
('CL', _('Castile and Leon')),
|
||||||
|
('CT', _('Catalonia')),
|
||||||
|
('EX', _('Extremadura')),
|
||||||
|
('GA', _('Galicia')),
|
||||||
|
('LO', _('La Rioja')),
|
||||||
|
('M', _('Madrid')),
|
||||||
|
('MU', _('Region of Murcia')),
|
||||||
|
('NA', _('Foral Community of Navarre')),
|
||||||
|
('VC', _('Valencian Community')),
|
||||||
|
)
|
||||||
|
|
|
@ -0,0 +1,173 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Spanish-specific Form helpers
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.newforms import ValidationError
|
||||||
|
from django.newforms.fields import RegexField, Select, EMPTY_VALUES
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
|
import re
|
||||||
|
|
||||||
|
class ESPostalCodeField(RegexField):
|
||||||
|
"""
|
||||||
|
A form field that validates its input as a spanish postal code.
|
||||||
|
|
||||||
|
Spanish postal code is a five digits string, with two first digits
|
||||||
|
between 01 and 52, assigned to provinces code.
|
||||||
|
"""
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(ESPostalCodeField, self).__init__(
|
||||||
|
r'^(0[1-9]|[1-4][0-9]|5[0-2])\d{3}$',
|
||||||
|
max_length=None, min_length=None,
|
||||||
|
error_message=_('Enter a valid postal code in the range and format 01XXX - 52XXX.'),
|
||||||
|
*args, **kwargs)
|
||||||
|
|
||||||
|
class ESPhoneNumberField(RegexField):
|
||||||
|
"""
|
||||||
|
A form field that validates its input as a Spanish phone number.
|
||||||
|
Information numbers are ommited.
|
||||||
|
|
||||||
|
Spanish phone numbers are nine digit numbers, where first digit is 6 (for
|
||||||
|
cell phones), 8 (for special phones), or 9 (for landlines and special
|
||||||
|
phones)
|
||||||
|
|
||||||
|
TODO: accept and strip characters like dot, hyphen... in phone number
|
||||||
|
"""
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(ESPhoneNumberField, self).__init__(r'^(6|8|9)\d{8}$',
|
||||||
|
max_length=None, min_length=None,
|
||||||
|
error_message=_('Enter a valid phone number in one of the formats 6XXXXXXXX, 8XXXXXXXX or 9XXXXXXXX.'),
|
||||||
|
*args, **kwargs)
|
||||||
|
|
||||||
|
class ESIdentityCardNumberField(RegexField):
|
||||||
|
"""
|
||||||
|
Spanish NIF/NIE/CIF (Fiscal Identification Number) code.
|
||||||
|
|
||||||
|
Validates three diferent formats:
|
||||||
|
|
||||||
|
NIF (individuals): 12345678A
|
||||||
|
CIF (companies): A12345678
|
||||||
|
NIE (foreigners): X12345678A
|
||||||
|
|
||||||
|
according to a couple of simple checksum algorithms.
|
||||||
|
|
||||||
|
Value can include a space or hyphen separator between number and letters.
|
||||||
|
Number length is not checked for NIF (or NIE), old values start with a 1,
|
||||||
|
and future values can contain digits greater than 8. The CIF control digit
|
||||||
|
can be a number or a letter depending on company type. Algorithm is not
|
||||||
|
public, and different authors have different opinions on which ones allows
|
||||||
|
letters, so both validations are assumed true for all types.
|
||||||
|
"""
|
||||||
|
def __init__(self, only_nif=False, *args, **kwargs):
|
||||||
|
self.only_nif = only_nif
|
||||||
|
self.nif_control = 'TRWAGMYFPDXBNJZSQVHLCKE'
|
||||||
|
self.cif_control = 'JABCDEFGHI'
|
||||||
|
self.cif_types = 'ABCDEFGHKLMNPQS'
|
||||||
|
self.nie_types = 'XT'
|
||||||
|
if self.only_nif:
|
||||||
|
self.id_types = 'NIF or NIE'
|
||||||
|
else:
|
||||||
|
self.id_types = 'NIF, NIE, or CIF'
|
||||||
|
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()),
|
||||||
|
max_length=None, min_length=None,
|
||||||
|
error_message=_('Please enter a valid %s.' % self.id_types),
|
||||||
|
*args, **kwargs)
|
||||||
|
|
||||||
|
def clean(self, value):
|
||||||
|
super(ESIdentityCardNumberField, self).clean(value)
|
||||||
|
if value in EMPTY_VALUES:
|
||||||
|
return u''
|
||||||
|
nif_get_checksum = lambda d: self.nif_control[int(d)%23]
|
||||||
|
|
||||||
|
value = value.upper().replace(' ', '').replace('-', '')
|
||||||
|
m = re.match(r'^([%s]?)[ -]?(\d+)[ -]?([%s]?)$' % (self.cif_types + self.nie_types, self.nif_control), value)
|
||||||
|
letter1, number, letter2 = m.groups()
|
||||||
|
|
||||||
|
if not letter1 and letter2:
|
||||||
|
# NIF
|
||||||
|
if letter2 == nif_get_checksum(number):
|
||||||
|
return value
|
||||||
|
else:
|
||||||
|
raise ValidationError, _('Invalid checksum for NIF.')
|
||||||
|
elif letter1 in self.nie_types and letter2:
|
||||||
|
# NIE
|
||||||
|
if letter2 == nif_get_checksum(number):
|
||||||
|
return value
|
||||||
|
else:
|
||||||
|
raise ValidationError, _('Invalid checksum for NIE.')
|
||||||
|
elif not self.only_nif and letter1 in self.cif_types and len(number) in [7, 8]:
|
||||||
|
# CIF
|
||||||
|
if not letter2:
|
||||||
|
number, letter2 = number[:-1], int(number[-1])
|
||||||
|
checksum = cif_get_checksum(number)
|
||||||
|
if letter2 in [checksum, self.cif_control[checksum]]:
|
||||||
|
return value
|
||||||
|
else:
|
||||||
|
raise ValidationError, _('Invalid checksum for CIF.')
|
||||||
|
else:
|
||||||
|
raise ValidationError, _('Please enter a valid %s.' % self.id_types)
|
||||||
|
|
||||||
|
class ESCCCField(RegexField):
|
||||||
|
"""
|
||||||
|
A form field that validates its input as a Spanish bank account or CCC
|
||||||
|
(Codigo Cuenta Cliente).
|
||||||
|
|
||||||
|
Spanish CCC is in format EEEE-OOOO-CC-AAAAAAAAAA where:
|
||||||
|
|
||||||
|
E = entity
|
||||||
|
O = office
|
||||||
|
C = checksum
|
||||||
|
A = account
|
||||||
|
|
||||||
|
It's also valid to use a space as delimiter, or to use no delimiter.
|
||||||
|
|
||||||
|
First checksum digit validates entity and office, and last one
|
||||||
|
validates account. Validation is done multiplying every digit of 10
|
||||||
|
digit value (with leading 0 if necessary) by number in its position in
|
||||||
|
string 1, 2, 4, 8, 5, 10, 9, 7, 3, 6. Sum resulting numbers and extract
|
||||||
|
it from 11. Result is checksum except when 10 then is 1, or when 11
|
||||||
|
then is 0.
|
||||||
|
|
||||||
|
TODO: allow IBAN validation too
|
||||||
|
"""
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(ESCCCField, self).__init__(r'^\d{4}[ -]?\d{4}[ -]?\d{2}[ -]?\d{10}$',
|
||||||
|
max_length=None, min_length=None,
|
||||||
|
error_message=_('Please enter a valid bank account number in format XXXX-XXXX-XX-XXXXXXXXXX.'),
|
||||||
|
*args, **kwargs)
|
||||||
|
|
||||||
|
def clean(self, value):
|
||||||
|
super(ESCCCField, self).clean(value)
|
||||||
|
if value in EMPTY_VALUES:
|
||||||
|
return u''
|
||||||
|
control_str = [1, 2, 4, 8, 5, 10, 9, 7, 3, 6]
|
||||||
|
m = re.match(r'^(\d{4})[ -]?(\d{4})[ -]?(\d{2})[ -]?(\d{10})$', value)
|
||||||
|
entity, office, checksum, account = m.groups()
|
||||||
|
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')
|
||||||
|
if get_checksum('00' + entity + office) + get_checksum(account) == checksum:
|
||||||
|
return value
|
||||||
|
else:
|
||||||
|
raise ValidationError, _('Invalid checksum for bank account number.')
|
||||||
|
|
||||||
|
class ESRegionSelect(Select):
|
||||||
|
"""
|
||||||
|
A Select widget that uses a list of spanish regions as its choices.
|
||||||
|
"""
|
||||||
|
def __init__(self, attrs=None):
|
||||||
|
from es_regions import REGION_CHOICES
|
||||||
|
super(ESRegionSelect, self).__init__(attrs, choices=REGION_CHOICES)
|
||||||
|
|
||||||
|
class ESProvinceSelect(Select):
|
||||||
|
"""
|
||||||
|
A Select widget that uses a list of spanish provinces as its choices.
|
||||||
|
"""
|
||||||
|
def __init__(self, attrs=None):
|
||||||
|
from es_provinces import PROVINCE_CHOICES
|
||||||
|
super(ESProvinceSelect, self).__init__(attrs, choices=PROVINCE_CHOICES)
|
||||||
|
|
||||||
|
|
||||||
|
def cif_get_checksum(number):
|
||||||
|
s1 = sum([int(digit) for pos, digit in enumerate(number) if int(pos) % 2])
|
||||||
|
s2 = sum([sum([int(unit) for unit in str(int(digit) * 2)]) for pos, digit in enumerate(number) if not int(pos) % 2])
|
||||||
|
return 10 - ((s1 + s2) % 10)
|
||||||
|
|
|
@ -0,0 +1,343 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Tests for the contrib/localflavor/ ES form fields.
|
||||||
|
|
||||||
|
tests = r"""
|
||||||
|
# ESPostalCodeField ##############################################################
|
||||||
|
|
||||||
|
ESPostalCodeField validates that data is a five-digit spanish postal code.
|
||||||
|
>>> from django.contrib.localflavor.es.forms import ESPostalCodeField
|
||||||
|
>>> f = ESPostalCodeField()
|
||||||
|
>>> f.clean('08028')
|
||||||
|
u'08028'
|
||||||
|
>>> f.clean('28080')
|
||||||
|
u'28080'
|
||||||
|
>>> f.clean('53001')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Enter a valid postal code in the range and format 01XXX - 52XXX.']
|
||||||
|
>>> f.clean('0801')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Enter a valid postal code in the range and format 01XXX - 52XXX.']
|
||||||
|
>>> f.clean('080001')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Enter a valid postal code in the range and format 01XXX - 52XXX.']
|
||||||
|
>>> f.clean('00999')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Enter a valid postal code in the range and format 01XXX - 52XXX.']
|
||||||
|
>>> f.clean('08 01')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Enter a valid postal code in the range and format 01XXX - 52XXX.']
|
||||||
|
>>> f.clean('08A01')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Enter a valid postal code in the range and format 01XXX - 52XXX.']
|
||||||
|
>>> f.clean('')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'This field is required.']
|
||||||
|
|
||||||
|
>>> f = ESPostalCodeField(required=False)
|
||||||
|
>>> f.clean('08028')
|
||||||
|
u'08028'
|
||||||
|
>>> f.clean('28080')
|
||||||
|
u'28080'
|
||||||
|
>>> f.clean('53001')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Enter a valid postal code in the range and format 01XXX - 52XXX.']
|
||||||
|
>>> f.clean('0801')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Enter a valid postal code in the range and format 01XXX - 52XXX.']
|
||||||
|
>>> f.clean('080001')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Enter a valid postal code in the range and format 01XXX - 52XXX.']
|
||||||
|
>>> f.clean('00999')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Enter a valid postal code in the range and format 01XXX - 52XXX.']
|
||||||
|
>>> f.clean('08 01')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Enter a valid postal code in the range and format 01XXX - 52XXX.']
|
||||||
|
>>> f.clean('08A01')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Enter a valid postal code in the range and format 01XXX - 52XXX.']
|
||||||
|
>>> f.clean('')
|
||||||
|
u''
|
||||||
|
|
||||||
|
# ESPhoneNumberField ##############################################################
|
||||||
|
|
||||||
|
ESPhoneNumberField validates that data is a nine-digit spanish phone number.
|
||||||
|
>>> from django.contrib.localflavor.es.forms import ESPhoneNumberField
|
||||||
|
>>> f = ESPhoneNumberField()
|
||||||
|
>>> f.clean('650010101')
|
||||||
|
u'650010101'
|
||||||
|
>>> f.clean('931234567')
|
||||||
|
u'931234567'
|
||||||
|
>>> f.clean('800123123')
|
||||||
|
u'800123123'
|
||||||
|
>>> f.clean('555555555')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Enter a valid phone number in one of the formats 6XXXXXXXX, 8XXXXXXXX or 9XXXXXXXX.']
|
||||||
|
>>> f.clean('789789789')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Enter a valid phone number in one of the formats 6XXXXXXXX, 8XXXXXXXX or 9XXXXXXXX.']
|
||||||
|
>>> f.clean('99123123')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Enter a valid phone number in one of the formats 6XXXXXXXX, 8XXXXXXXX or 9XXXXXXXX.']
|
||||||
|
>>> f.clean('9999123123')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Enter a valid phone number in one of the formats 6XXXXXXXX, 8XXXXXXXX or 9XXXXXXXX.']
|
||||||
|
>>> f.clean('')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'This field is required.']
|
||||||
|
|
||||||
|
>>> f = ESPhoneNumberField(required=False)
|
||||||
|
>>> f.clean('650010101')
|
||||||
|
u'650010101'
|
||||||
|
>>> f.clean('931234567')
|
||||||
|
u'931234567'
|
||||||
|
>>> f.clean('800123123')
|
||||||
|
u'800123123'
|
||||||
|
>>> f.clean('555555555')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Enter a valid phone number in one of the formats 6XXXXXXXX, 8XXXXXXXX or 9XXXXXXXX.']
|
||||||
|
>>> f.clean('789789789')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Enter a valid phone number in one of the formats 6XXXXXXXX, 8XXXXXXXX or 9XXXXXXXX.']
|
||||||
|
>>> f.clean('99123123')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Enter a valid phone number in one of the formats 6XXXXXXXX, 8XXXXXXXX or 9XXXXXXXX.']
|
||||||
|
>>> f.clean('9999123123')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Enter a valid phone number in one of the formats 6XXXXXXXX, 8XXXXXXXX or 9XXXXXXXX.']
|
||||||
|
>>> f.clean('')
|
||||||
|
u''
|
||||||
|
|
||||||
|
# ESIdentityCardNumberField ##############################################################
|
||||||
|
|
||||||
|
ESIdentityCardNumberField validates that data is a identification spanish code for companies or individuals (CIF, NIF or NIE).
|
||||||
|
>>> from django.contrib.localflavor.es.forms import ESIdentityCardNumberField
|
||||||
|
>>> f = ESIdentityCardNumberField()
|
||||||
|
>>> f.clean('78699688J')
|
||||||
|
'78699688J'
|
||||||
|
>>> f.clean('78699688-J')
|
||||||
|
'78699688J'
|
||||||
|
>>> f.clean('78699688 J')
|
||||||
|
'78699688J'
|
||||||
|
>>> f.clean('78699688 j')
|
||||||
|
'78699688J'
|
||||||
|
>>> f.clean('78699688T')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Invalid checksum for NIF.']
|
||||||
|
>>> f.clean('X0901797J')
|
||||||
|
'X0901797J'
|
||||||
|
>>> f.clean('X-6124387-Q')
|
||||||
|
'X6124387Q'
|
||||||
|
>>> f.clean('X 0012953 G')
|
||||||
|
'X0012953G'
|
||||||
|
>>> f.clean('x-3287690-r')
|
||||||
|
'X3287690R'
|
||||||
|
>>> f.clean('t-03287690r')
|
||||||
|
'T03287690R'
|
||||||
|
>>> f.clean('X-03287690')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Please enter a valid NIF, NIE, or CIF.']
|
||||||
|
>>> f.clean('X-03287690-T')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Invalid checksum for NIE.']
|
||||||
|
>>> f.clean('B38790911')
|
||||||
|
'B38790911'
|
||||||
|
>>> f.clean('B-3879091A')
|
||||||
|
'B3879091A'
|
||||||
|
>>> f.clean('B 38790917')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Invalid checksum for CIF.']
|
||||||
|
>>> f.clean('B 38790911')
|
||||||
|
'B38790911'
|
||||||
|
>>> f.clean('P-3900800-H')
|
||||||
|
'P3900800H'
|
||||||
|
>>> f.clean('P 39008008')
|
||||||
|
'P39008008'
|
||||||
|
>>> f.clean('C-28795565')
|
||||||
|
'C28795565'
|
||||||
|
>>> f.clean('C 2879556E')
|
||||||
|
'C2879556E'
|
||||||
|
>>> f.clean('C28795567')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Invalid checksum for CIF.']
|
||||||
|
>>> f.clean('I38790911')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Please enter a valid NIF, NIE, or CIF.']
|
||||||
|
>>> f.clean('78699688-2')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Please enter a valid NIF, NIE, or CIF.']
|
||||||
|
>>> f.clean('')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'This field is required.']
|
||||||
|
|
||||||
|
>>> f = ESIdentityCardNumberField(required=False)
|
||||||
|
>>> f.clean('78699688J')
|
||||||
|
'78699688J'
|
||||||
|
>>> f.clean('78699688-J')
|
||||||
|
'78699688J'
|
||||||
|
>>> f.clean('78699688 J')
|
||||||
|
'78699688J'
|
||||||
|
>>> f.clean('78699688 j')
|
||||||
|
'78699688J'
|
||||||
|
>>> f.clean('78699688T')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Invalid checksum for NIF.']
|
||||||
|
>>> f.clean('X0901797J')
|
||||||
|
'X0901797J'
|
||||||
|
>>> f.clean('X-6124387-Q')
|
||||||
|
'X6124387Q'
|
||||||
|
>>> f.clean('X 0012953 G')
|
||||||
|
'X0012953G'
|
||||||
|
>>> f.clean('x-3287690-r')
|
||||||
|
'X3287690R'
|
||||||
|
>>> f.clean('t-03287690r')
|
||||||
|
'T03287690R'
|
||||||
|
>>> f.clean('X-03287690')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Please enter a valid NIF, NIE, or CIF.']
|
||||||
|
>>> f.clean('X-03287690-T')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Invalid checksum for NIE.']
|
||||||
|
>>> f.clean('B38790911')
|
||||||
|
'B38790911'
|
||||||
|
>>> f.clean('B-3879091A')
|
||||||
|
'B3879091A'
|
||||||
|
>>> f.clean('B 38790917')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Invalid checksum for CIF.']
|
||||||
|
>>> f.clean('B 38790911')
|
||||||
|
'B38790911'
|
||||||
|
>>> f.clean('P-3900800-H')
|
||||||
|
'P3900800H'
|
||||||
|
>>> f.clean('P 39008008')
|
||||||
|
'P39008008'
|
||||||
|
>>> f.clean('C-28795565')
|
||||||
|
'C28795565'
|
||||||
|
>>> f.clean('C 2879556E')
|
||||||
|
'C2879556E'
|
||||||
|
>>> f.clean('C28795567')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Invalid checksum for CIF.']
|
||||||
|
>>> f.clean('I38790911')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Please enter a valid NIF, NIE, or CIF.']
|
||||||
|
>>> f.clean('78699688-2')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Please enter a valid NIF, NIE, or CIF.']
|
||||||
|
>>> f.clean('')
|
||||||
|
u''
|
||||||
|
|
||||||
|
# ESCCCField ##############################################################
|
||||||
|
|
||||||
|
ESCCCField validates that data is a spanish bank account number (codigo cuenta cliente).
|
||||||
|
|
||||||
|
>>> from django.contrib.localflavor.es.forms import ESCCCField
|
||||||
|
>>> f = ESCCCField()
|
||||||
|
>>> f.clean('20770338793100254321')
|
||||||
|
'20770338793100254321'
|
||||||
|
>>> f.clean('2077 0338 79 3100254321')
|
||||||
|
'2077 0338 79 3100254321'
|
||||||
|
>>> f.clean('2077-0338-79-3100254321')
|
||||||
|
'2077-0338-79-3100254321'
|
||||||
|
>>> f.clean('2077.0338.79.3100254321')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Please enter a valid bank account number in format XXXX-XXXX-XX-XXXXXXXXXX.']
|
||||||
|
>>> f.clean('2077-0338-78-3100254321')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Invalid checksum for bank account number.']
|
||||||
|
>>> f.clean('2077-0338-89-3100254321')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Invalid checksum for bank account number.']
|
||||||
|
>>> f.clean('2077-03-3879-3100254321')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Please enter a valid bank account number in format XXXX-XXXX-XX-XXXXXXXXXX.']
|
||||||
|
>>> f.clean('')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'This field is required.']
|
||||||
|
|
||||||
|
>>> f = ESCCCField(required=False)
|
||||||
|
>>> f.clean('20770338793100254321')
|
||||||
|
'20770338793100254321'
|
||||||
|
>>> f.clean('2077 0338 79 3100254321')
|
||||||
|
'2077 0338 79 3100254321'
|
||||||
|
>>> f.clean('2077-0338-79-3100254321')
|
||||||
|
'2077-0338-79-3100254321'
|
||||||
|
>>> f.clean('2077.0338.79.3100254321')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Please enter a valid bank account number in format XXXX-XXXX-XX-XXXXXXXXXX.']
|
||||||
|
>>> f.clean('2077-0338-78-3100254321')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Invalid checksum for bank account number.']
|
||||||
|
>>> f.clean('2077-0338-89-3100254321')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Invalid checksum for bank account number.']
|
||||||
|
>>> f.clean('2077-03-3879-3100254321')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Please enter a valid bank account number in format XXXX-XXXX-XX-XXXXXXXXXX.']
|
||||||
|
>>> f.clean('')
|
||||||
|
u''
|
||||||
|
|
||||||
|
# ESRegionSelect ##############################################################
|
||||||
|
|
||||||
|
ESRegionSelect is a Select widget that uses a list of Spain regions as its choices.
|
||||||
|
>>> from django.contrib.localflavor.es.forms import ESRegionSelect
|
||||||
|
>>> w = ESRegionSelect()
|
||||||
|
>>> w.render('regions', 'CT')
|
||||||
|
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>'
|
||||||
|
|
||||||
|
# ESProvincenSelect ##############################################################
|
||||||
|
|
||||||
|
ESProvinceSelect is a Select widget that uses a list of Spain provinces as its choices.
|
||||||
|
>>> from django.contrib.localflavor.es.forms import ESProvinceSelect
|
||||||
|
>>> w = ESProvinceSelect()
|
||||||
|
>>> w.render('provinces', '08')
|
||||||
|
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>'
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
|
@ -9,6 +9,7 @@ from localflavor.ca import tests as localflavor_ca_tests
|
||||||
from localflavor.ch import tests as localflavor_ch_tests
|
from localflavor.ch import tests as localflavor_ch_tests
|
||||||
from localflavor.cl import tests as localflavor_cl_tests
|
from localflavor.cl import tests as localflavor_cl_tests
|
||||||
from localflavor.de import tests as localflavor_de_tests
|
from localflavor.de import tests as localflavor_de_tests
|
||||||
|
from localflavor.es import tests as localflavor_es_tests
|
||||||
from localflavor.fi import tests as localflavor_fi_tests
|
from localflavor.fi import tests as localflavor_fi_tests
|
||||||
from localflavor.fr import tests as localflavor_fr_tests
|
from localflavor.fr import tests as localflavor_fr_tests
|
||||||
from localflavor.generic import tests as localflavor_generic_tests
|
from localflavor.generic import tests as localflavor_generic_tests
|
||||||
|
@ -35,6 +36,7 @@ __test__ = {
|
||||||
'localflavor_ch_tests': localflavor_ch_tests,
|
'localflavor_ch_tests': localflavor_ch_tests,
|
||||||
'localflavor_cl_tests': localflavor_cl_tests,
|
'localflavor_cl_tests': localflavor_cl_tests,
|
||||||
'localflavor_de_tests': localflavor_de_tests,
|
'localflavor_de_tests': localflavor_de_tests,
|
||||||
|
'localflavor_es_tests': localflavor_es_tests,
|
||||||
'localflavor_fi_tests': localflavor_fi_tests,
|
'localflavor_fi_tests': localflavor_fi_tests,
|
||||||
'localflavor_fr_tests': localflavor_fr_tests,
|
'localflavor_fr_tests': localflavor_fr_tests,
|
||||||
'localflavor_generic_tests': localflavor_generic_tests,
|
'localflavor_generic_tests': localflavor_generic_tests,
|
||||||
|
|
Loading…
Reference in New Issue