Ticket #4036: es.diff

File es.diff, 16.3 KB (added by Simon G. <dev@…>, 8 years ago)

Patch from ricardojbarrios@.. that I've just svn diff'ed

  • contrib/localflavor/es/es_province.py

     
     1# -*- coding: utf-8 -*-
     2"""
     3An alphabetical list of spanish provinces, including two autonomous
     4cities, for use as `choices` in a formfield.
     5
     6This exists in this standalone file so that it's only imported into
     7memory when explicitly needed.
     8"""
     9
     10PROVINCE_CHOICES = (
     11    ('VI', u'Álava'),
     12    ('AB', u'Albacete'),
     13    ('A', u'Alicante'),
     14    ('AL', u'Almería'),
     15    ('O', u'Asturias'),
     16    ('AV', u'Ávila'),
     17    ('BA', u'Badajoz'),
     18    ('PM', u'Islas Baleares'),
     19    ('B', u'Barcelona'),
     20    ('Bu', u'Burgos'),
     21    ('CC', u'Cáceres'),
     22    ('CA', u'Cádiz'),
     23    ('S', u'Cantabria'),
     24    ('CS', u'Castellón'),
     25    ('CE', u'Ceuta'),
     26    ('CR', u'Ciudad Real'),
     27    ('CO', u'Córdoba'),
     28    ('Cu', u'Cuenca'),
     29    ('GI', u'Gerona'),
     30    ('GR', u'Granada'),
     31    ('Gu', u'Guadalajara'),
     32    ('SS', u'Guipúzcoa'),
     33    ('H', u'Huelva'),
     34    ('Hu', u'Huesca'),
     35    ('J', u'Jaén'),
     36    ('C', u'La Coruña'),           
     37    ('LO', u'La Rioja'),
     38    ('GC', u'Las Palmas'),
     39    ('LE', u'León'),
     40    ('L', u'Lérida'),
     41    ('Lu', u'Lugo'),
     42    ('M', u'Madrid'),
     43    ('MA', u'Málaga'),
     44    ('ML', u'Melilla'),
     45    ('Mu', u'Murcia'),
     46    ('NA', u'Navarra'),
     47    ('OR', u'Orense'),
     48    ('P', u'Palencia'),
     49    ('PO', u'Pontevedra'),
     50    ('SA', u'Salamanca'),
     51    ('TF', u'Santa Cruz de Tenerife'),
     52    ('SG', u'Segovia'),
     53    ('SE', u'Sevilla'),
     54    ('SO', u'Soria'),
     55    ('T', u'Tarragona'),
     56    ('TE', u'Teruel'),
     57    ('TO', u'Toledo'),
     58    ('V', u'Valencia'),
     59    ('VA', u'Valladolid'),
     60    ('BI', u'Vizcaya'),
     61    ('ZA', u'Zamora'),
     62    ('Z', u'Zaragoza'),
     63)
  • contrib/localflavor/es/test.py

     
     1"""
     2# ESPostalCodeField #############################################################
     3
     4ESPostalCodeField validates that the data is a valid ES postal code.
     5>>> from django.contrib.localflavor.es.forms import ESPostalCodeField
     6>>> f = ESPostalCodeField()
     7>>> f.clean('01000')
     8u'01000'
     9>>> f.clean('52999')
     10u'52999'
     11>>> f.clean('00999')
     12Traceback (most recent call last):
     13...
     14ValidationError: [u'Enter a valid postal code in the format XXXXX.']
     15>>> f.clean('53000')
     16Traceback (most recent call last):
     17...
     18ValidationError: [u'Enter a valid postal code in the format XXXXX.']
     19>>> f.clean('2A200')
     20Traceback (most recent call last):
     21...
     22ValidationError: [u'Enter a valid postal code in the format XXXXX.']
     23>>> f.clean('380001')
     24Traceback (most recent call last):
     25...
     26ValidationError: [u'Enter a valid postal code in the format XXXXX.']
     27>>> f.clean(None)
     28Traceback (most recent call last):
     29...
     30ValidationError: [u'This field is required.']
     31>>> f.clean('')
     32Traceback (most recent call last):
     33...
     34ValidationError: [u'This field is required.']
     35
     36>>> f = ESPostalCodeField(required=False)
     37>>> f.clean('01000')
     38u'01000'
     39>>> f.clean('52999')
     40u'52999'
     41>>> f.clean('00999')
     42Traceback (most recent call last):
     43...
     44ValidationError: [u'Enter a valid postal code in the format XXXXX.']
     45>>> f.clean('53000')
     46Traceback (most recent call last):
     47...
     48ValidationError: [u'Enter a valid postal code in the format XXXXX.']
     49>>> f.clean('2A200')
     50Traceback (most recent call last):
     51...
     52ValidationError: [u'Enter a valid postal code in the format XXXXX.']
     53>>> f.clean('380001')
     54Traceback (most recent call last):
     55...
     56ValidationError: [u'Enter a valid postal code in the format XXXXX.']
     57>>> f.clean(None)
     58u''
     59>>> f.clean('')
     60u''
     61
     62# ESSubdivisionSelect ###############################################################
     63
     64ESSubdivisionSelect
     65>>> from django.contrib.localflavor.es.forms import ESSubdivisionSelect
     66>>> w = ESSubdivisionSelect()
     67>>> w.render('provinces', 'TF')
     68u'<select name="provinces">\n<option value="VI">\xc1lava</option>\n<option value="AB">Albacete</option>\n<option value="A">Alicante</option>\n<option value="AL">Almer\xeda</option>\n<option value="O">Asturias</option>\n<option value="AV">\xc1vila</option>\n<option value="BA">Badajoz</option>\n<option value="PM">Islas Baleares</option>\n<option value="B">Barcelona</option>\n<option value="Bu">Burgos</option>\n<option value="CC">C\xe1ceres</option>\n<option value="CA">C\xe1diz</option>\n<option value="S">Cantabria</option>\n<option value="CS">Castell\xf3n</option>\n<option value="CE">Ceuta</option>\n<option value="CR">Ciudad Real</option>\n<option value="CO">C\xf3rdoba</option>\n<option value="Cu">Cuenca</option>\n<option value="GI">Gerona</option>\n<option value="GR">Granada</option>\n<option value="Gu">Guadalajara</option>\n<option value="SS">Guip\xfazcoa</option>\n<option value="H">Huelva</option>\n<option value="Hu">Huesca</option>\n<option value="J">Ja\xe9n</option>\n<option value="C">La Coru\xf1a</option>\n<option value="LO">La Rioja</option>\n<option value="GC">Las Palmas</option>\n<option value="LE">Le\xf3n</option>\n<option value="L">L\xe9rida</option>\n<option value="Lu">Lugo</option>\n<option value="M">Madrid</option>\n<option value="MA">M\xe1laga</option>\n<option value="ML">Melilla</option>\n<option value="Mu">Murcia</option>\n<option value="NA">Navarra</option>\n<option value="OR">Orense</option>\n<option value="P">Palencia</option>\n<option value="PO">Pontevedra</option>\n<option value="SA">Salamanca</option>\n<option value="TF" selected="selected">Santa Cruz de Tenerife</option>\n<option value="SG">Segovia</option>\n<option value="SE">Sevilla</option>\n<option value="SO">Soria</option>\n<option value="T">Tarragona</option>\n<option value="TE">Teruel</option>\n<option value="TO">Toledo</option>\n<option value="V">Valencia</option>\n<option value="VA">Valladolid</option>\n<option value="BI">Vizcaya</option>\n<option value="ZA">Zamora</option>\n<option value="Z">Zaragoza</option>\n</select>'
     69
     70# ESIdentityCardNumberField #############################################################
     71
     72ESIdentityCardNumberField
     73>>> from django.contrib.localflavor.es.forms import ESIdentityCardNumberField
     74>>> f = ESIdentityCardNumberField()
     75>>> f.clean('78699688')
     76u'78699688J'
     77>>> f.clean('78699688J')
     78u'78699688J'
     79>>> f.clean('78699688-J')
     80u'78699688J'
     81>>> f.clean('78699688 J')
     82u'78699688J'
     83>>> f.clean('78699688 j')
     84u'78699688J'
     85>>> f.clean('78699688T')
     86Traceback (most recent call last):
     87...
     88ValidationError: [u"The NIF you entered isn't valid. It should be 78699688J"]
     89>>> f.clean('X0901797J')
     90u'X0901797J'
     91>>> f.clean('X-6124387-Q')
     92u'X6124387Q'
     93>>> f.clean('X 0012953 G')
     94u'X0012953G'
     95>>> f.clean('x-3287690-r')
     96u'X3287690R'
     97>>> f.clean('X-03287690r')
     98u'X03287690R'
     99>>> f.clean('X-03287690')
     100u'X03287690R'
     101>>> f.clean('X-03287690-T')
     102Traceback (most recent call last):
     103...
     104ValidationError: [u"The NIE you entered isn't valid. It should be X03287690R"]
     105>>> f.clean('B38790911')
     106u'B38790911'
     107>>> f.clean('B-3879091A')
     108Traceback (most recent call last):
     109...
     110ValidationError: [u"The CIF you entered isn't valid. It should be B38790911"]
     111>>> f.clean('B 38790917')
     112Traceback (most recent call last):
     113...
     114ValidationError: [u"The CIF you entered isn't valid. It should be B38790911"]
     115>>> f.clean('P-3900800-H')
     116u'P3900800H'
     117>>> f.clean('P 39008008')
     118Traceback (most recent call last):
     119...
     120ValidationError: [u"The CIF you entered isn't valid. It should be P3900800H"]
     121>>> f.clean('C-28795565')
     122u'C28795565'
     123>>> f.clean('C 2879556E')
     124u'C2879556E'
     125>>> f.clean('C28795567')
     126Traceback (most recent call last):
     127...
     128ValidationError: [u"The CIF you entered isn't valid. It should be C2879556E or C28795565"]
     129>>> f.clean('I38790911')
     130Traceback (most recent call last):
     131...
     132ValidationError: [u"The CIF you entered isn't valid. It must start with A,B,C,D,E,F,G,H,K,L,M,N,P,Q or S"]
     133>>> f.clean('78699688-2')
     134Traceback (most recent call last):
     135...
     136ValidationError: [u'Please, enter a valid CIF, NIF or NIE.']
     137>>> f.clean('999999999')
     138Traceback (most recent call last):
     139...
     140ValidationError: [u'Please, enter a valid CIF, NIF or NIE.']
     141>>> f.clean(None)
     142Traceback (most recent call last):
     143...
     144ValidationError: [u'This field is required.']
     145>>> f.clean('')
     146Traceback (most recent call last):
     147...
     148ValidationError: [u'This field is required.']
     149>>> f = ESIdentityCardNumberField(required=False)
     150>>> f.clean(None)
     151u''
     152>>> f.clean('')
     153u''
     154>>> f = ESIdentityCardNumberField(show_correct=False)
     155>>> f.clean('78699688J')
     156u'78699688J'
     157>>> f.clean('78699688T')
     158Traceback (most recent call last):
     159...
     160ValidationError: [u'Please, enter a valid NIF.']
     161>>> f.clean('X-03287690-T')
     162Traceback (most recent call last):
     163...
     164ValidationError: [u'Please, enter a valid NIE.']
     165>>> f.clean('B-3879091A')
     166Traceback (most recent call last):
     167...
     168ValidationError: [u'Please, enter a valid CIF.']
     169>>> f.clean('P 39008008')
     170Traceback (most recent call last):
     171...
     172ValidationError: [u'Please, enter a valid CIF.']
     173>>> f.clean('C28795567')
     174Traceback (most recent call last):
     175...
     176ValidationError: [u'Please, enter a valid CIF.']
     177>>> f = ESIdentityCardNumberField(calc_control=False)
     178>>> f.clean('78699688J')
     179u'78699688J'
     180>>> f.clean('78699688')
     181Traceback (most recent call last):
     182...
     183ValidationError: [u'Please, enter a valid NIF.']
     184>>> f.clean('X-03287690')
     185Traceback (most recent call last):
     186...
     187ValidationError: [u'Please, enter a valid NIE.']
     188>>> f = ESIdentityCardNumberField(cif=False)
     189>>> f.clean('78699688J')
     190u'78699688J'
     191>>> f.clean('X-6124387-Q')
     192u'X6124387Q'
     193>>> f.clean('B38790911')
     194Traceback (most recent call last):
     195...
     196ValidationError: [u'Please, enter a valid NIF or NIE.']
     197>>> f = ESIdentityCardNumberField(nif=False)
     198>>> f.clean('78699688J')
     199Traceback (most recent call last):
     200...
     201ValidationError: [u'Please, enter a valid CIF.']
     202>>> f.clean('X-6124387-Q')
     203Traceback (most recent call last):
     204...
     205ValidationError: [u'Please, enter a valid CIF.']
     206>>> f.clean('B38790911')
     207u'B38790911'
     208"""
  • contrib/localflavor/es/forms.py

     
     1"""
     2Spanish-specific Form helpers
     3"""
     4
     5from django.newforms import ValidationError
     6from django.newforms.fields import RegexField, Select, EMPTY_VALUES
     7from django.utils.translation import gettext
     8import re
     9
     10class ESPostalCodeField(RegexField):
     11    """
     12    A form field that validates its input is a spanish postal code.
     13   
     14    Spanish postal code is a five digits string, with two first digits
     15    between 01 and 52, assigned to provinces code.
     16    """
     17    def __init__(self, *args, **kwargs):
     18        super(ESPostalCodeField, self).__init__(r'^([1-4]\d|0[^0]|5[012])\d{3}$',
     19            max_length=None, min_length=None,
     20            error_message=gettext(u'Enter a valid postal code in the format XXXXX.'),
     21            *args, **kwargs)
     22
     23
     24class ESSubdivisionSelect(Select):
     25    """
     26    A Select widget that uses a list of spanish provinces and autonomous
     27    cities as its choices.
     28    """
     29    def __init__(self, attrs=None):
     30        from es_province import PROVINCE_CHOICES
     31        super(ESSubdivisionSelect, self).__init__(attrs, choices=PROVINCE_CHOICES)
     32
     33
     34class ESIdentityCardNumberField(RegexField):
     35    """
     36    A form field that validates its input as an spanish NIF, CIF or NIE
     37   
     38    It acepts four new arguments:
     39    nif
     40        accept NIF or NIE
     41    cif
     42        accept CIF
     43    show_correct
     44        show the correct value if it's not valid
     45    calc_control
     46        calculate the control character of NIF and NIE if it's not present
     47    """   
     48    def _nif(self, dni):
     49        return "TRWAGMYFPDXBNJZSQVHLCKE"[long(dni)%23]
     50
     51    def __init__(self, nif=True, cif=True, show_correct=True, calc_control=True, *args, **kwargs):
     52        super(ESIdentityCardNumberField, self).__init__(r'^(\d{8}((-|\s|)[A-Za-z]{1}|)|([Xx](-|\s|)(\d{7}|\d{8})((-|\s|)[A-Za-z]{1}|))|([A-Sa-s]{1}(-|\s|)\d{7}(-|\s|)[A-Za-z0-9]{1}))$',
     53            max_length=None, min_length=None,
     54            error_message=gettext(u'Please, enter a valid CIF, NIF or NIE.'),
     55            *args, **kwargs)
     56        self.show_correct = show_correct
     57        self.calc_control = calc_control
     58        self.nif = nif
     59        self.cif = cif
     60        # What raise if nif and cif are false?
     61
     62    def clean(self, value):
     63        super(ESIdentityCardNumberField, self).clean(value)       
     64        if value in EMPTY_VALUES:
     65            return u''
     66        value = value.replace('-','').replace(' ','').upper()
     67        fchar = value[0]
     68        lchar = value[-1]
     69        nif_error_msg = gettext(u'Please, enter a valid NIF.')
     70        nie_error_msg = gettext(u'Please, enter a valid NIE.')
     71        nifnie_error_msg = gettext(u'Please, enter a valid NIF or NIE.')
     72        cif_error_msg = gettext(u'Please, enter a valid CIF.')
     73        if fchar.isdigit(): # Validate or calculate NIF
     74            if not self.nif:
     75                raise ValidationError(cif_error_msg)     
     76            if not self.calc_control and len(value) == 8:
     77                raise ValidationError(nif_error_msg)
     78            dni = value[:8]
     79            nif = '%s%s' % (dni, self._nif(dni))
     80            if lchar.isalpha() and value != nif:
     81                if self.show_correct:
     82                    raise ValidationError(gettext(u'The NIF you entered isn\'t valid. It should be %(nif)s' % {'nif': nif}))
     83                else:
     84                    raise ValidationError(nif_error_msg)
     85            return u'%s' % nif
     86        elif fchar == 'X': # Validate or calculate NIE
     87            if not self.nif:
     88                raise ValidationError(cif_error_msg)
     89            if not self.calc_control and not lchar.isalpha():
     90                raise ValidationError(nie_error_msg)
     91            dni = value[1:]
     92            if lchar.isalpha():
     93                dni = dni[:-1]
     94            nie = 'X%s%s' % (dni, self._nif(dni))
     95            if lchar.isalpha() and value != nie:
     96                if self.show_correct:
     97                    raise ValidationError(gettext(u'The NIE you entered isn\'t valid. It should be %(nie)s' % {'nie': nie}))
     98                else:
     99                    raise ValidationError(nie_error_msg)
     100            return u'%s' % nie
     101        else: # Validate CIF     
     102            if not self.cif:
     103                raise ValidationError(nifnie_error_msg)       
     104            if not fchar in 'ABCDEFGHKLMNPQS':
     105                raise ValidationError(gettext(u'The CIF you entered isn\'t valid. It must start with A,B,C,D,E,F,G,H,K,L,M,N,P,Q or S'))
     106            digits = value[1:8]
     107            a = int(digits[1]) + int(digits[3]) + int(digits[5])
     108            b = 0
     109            for d in [digits[0], digits[2], digits[4], digits[6]]:
     110                v= str(int(d) * 2)
     111                if len(v) == 2:
     112                    v = int(v[0]) + int(v[1])
     113                b = b + int(v)
     114            control = 10 - int(str(a + b)[-1])
     115            if fchar in 'KPQS':
     116                cif = '%s%s%s' % (fchar, digits, "JABCDEFGHI"[control])
     117                if value != cif:
     118                    if self.show_correct:
     119                        raise ValidationError(gettext(u'The CIF you entered isn\'t valid. It should be %(cif)s' % {'cif': cif}))
     120                    else:
     121                        raise ValidationError(cif_error_msg)
     122            elif fchar in 'ABEH':
     123                cif = '%s%s%s' % (fchar, digits, control)
     124                if value != cif:
     125                    if self.show_correct:
     126                        raise ValidationError(gettext(u'The CIF you entered isn\'t valid. It should be %(cif)s' % {'cif': cif}))
     127                    else:
     128                        raise ValidationError(cif_error_msg)
     129            else:
     130                cif1 = '%s%s%s' % (fchar, digits, "JABCDEFGHI"[control])
     131                cif2 = '%s%s%s' % (fchar, digits, control)
     132                if value != cif1 and value != cif2:
     133                    if self.show_correct:
     134                        raise ValidationError(gettext(u'The CIF you entered isn\'t valid. It should be %(cif1)s or %(cif2)s' % {'cif1': cif1, 'cif2': cif2}))
     135                    else:
     136                        raise ValidationError(cif_error_msg)
     137            return u'%s' % value
Back to Top