Login

Spanish National Identification Number Field (DNI)

Author:
cues7a
Posted:
June 15, 2011
Language:
Python
Version:
1.3
Tags:
validation dni custom fields nif nid nie
Score:
0 (after 0 ratings)

This django field can be used to introduce Spanish national Identification Numbers (NIF). It validates the NIF format and checks if the last letter is correct.

It also validates NIE numbers for foreign people.

You can use the field in your own forms:

'code' dni = DNIField(max_length=15, widget=forms.TextInput(), label=_('DNI')) 'code'

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
def fiscal_letter(fiscal_num=None):   
    """return the correct letter for the fiscal_num param"""
    if fiscal_num:
        result = fiscal_num%23
        letters='TRWAGMYFPDXBNJZSQVHLCKE'
        return letters[result]   
    return fiscal_num

def is_valid_id(dni_type, number):
    """"""
    is_valid = False
    if dni_type == 'nif' :
        if number[0:8].isdigit() and len(number) == 9:                   
            letter = fiscal_letter(int(number[0:8]))
            is_valid = number[8].upper() == letter
    
    elif dni_type == 'nie':
        correct_length = len(number) == 10 or len(number) == 9
        correct_letter = number[0].upper() == 'X' or number[0].upper() == 'Y'
        correct_digits = number[1:len(number)-1].isdigit()

        if correct_digits and correct_length and correct_letter:                   
            letter = fiscal_letter(int(number[1:-1]))
            is_valid = number[-1].upper() == letter                               
    else:
        is_valid=True
    
    return is_valid

#
#
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError

class DNIField(CharField):
    default_error_messages = {
       'invalid': _('Please, enter a valid DNI'),
    }

    def clean(self, value):
        super(CharField, self).clean(value)
        if value in EMPTY_VALUES:
               return u''

        first_letter = value[0]
        type_id = "nif"
        try:
           int(first_letter)
        except ValueError:
           type_id = "nie"
        
        if is_valid_id(type_id, value):
             return value

        raise ValidationError(self.error_messages['invalid'])

More like this

Comments

esauro (on June 16, 2011):
<p>Congrats for publishing a snippet and share your work with the community. However, wasn't this solved with spanish localflavor?</p>

#

cues7a (on June 16, 2011):
<p>Oh, you are right! </p> <p>I didn't know the field was already done in local flavours module,</p> <p>Thank you.</p>

#

Please login first before commenting.