Si vas a crear un formulario donde se pueda introducir un DNI/NIF no necesitas crear tu propio DNIField o programar un validador, ya existe en un paquete llamado django-localflavor que agrupa ese tipo de campos para los distintos países.

Por ejemplo para España incluye:

  • ESPhoneNumberField - Números de teléfonos fijos y móviles.
  • ESIdentityCardNumberField - Numero de identificación NIF/CIF/NIE.
  • ESCCCField - Código de cuenta de cliente en formato EEEE-OOOO-CC-AAAAAAAAAA
  • ESProvinceSelect - Selección de provincia.

Instalación

Como siempre pip es la mejor opción para instalar el paquete:

$ pip install django-localflavor

Luego añade 'localflavor' a INSTALLED_APPS en settings.conf:

INSTALLED_APPS = (
    # ...
    'localflavor',
)

Uso

Un ejemplo de como crear un formulario sencillo:

#forms.py
from django import forms
from localflavor.es.forms import ESIdentityCardNumberField, ESPhoneNumberField, ESProvinceField

class ClienteForm(forms.Form):
    nombre = forms.CharField(max_length=200)
    dni = ESIdentityCardNumberField(only_nif=True)
    telefono = ESPhoneNumberField()
    ...

Al campo dni se le ha añadido la opción only_nif=True para que sólo acepte NIF y NIE (Numero identificación extranjeros), sin ella también aceptaría códigos CIF.

Ver comentarios