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

  1. Newforms Validation of Credit Card Numbers by humphreymurray 7 years, 2 months ago
  2. UKPhoneNumberField by nathan-reynolds 6 years, 8 months ago
  3. UKPhoneNumberField GB v2 by g1smd 2 years, 10 months ago
  4. UKPhoneNumberField GB v3 (improved) by g1smd 2 years, 10 months ago
  5. models.MultipleEmailField by fero 3 years, 6 months ago

Comments

esauro (on June 16, 2011):

Congrats for publishing a snippet and share your work with the community. However, wasn't this solved with spanish localflavor?

#

cues7a (on June 16, 2011):

Oh, you are right!

I didn't know the field was already done in local flavours module,

Thank you.

#

Please login first before commenting.