Hello,

I'm trying to write a custom field for use with the netaddr.EUI python
class (which allows manipulations on MAC Addresses, access to the OUI
database, and other fancy stuff).

To do so, I'm subclassing model.Field, and overriding the to_python and
get_prep_value methods. The class instantiation in to_python can raise
an exception when the format is wrong. I catch this exception and
re-raise a ValidationError.

Unfortunately, when doing a form validation, this ValidationError throws
an error 500 instead of pretty-printing the message in the form. Am I
doing something wrong?

See the relevant snippets below:

#------8<----{ fields.py }---->8------#
import netaddr
 
from django.core.exceptions import ValidationError
from django.db import models
 
#[...]

class MACAddressField(models.Field):

    description = "A MAC Address"

    __metaclass__ = models.SubfieldBase

    def __init__(self, *args, **kwargs):
        kwargs['max_length'] = 12
        super(MACAddressField, self).__init__(*args, **kwargs)

    def to_python(self, value):
        if not isinstance(value, netaddr.EUI):
            try:
                value = netaddr.EUI(value)
            except netaddr.AddrFormatError as e:
                raise FormValidationError("Adresse MAC invalide: %s" % 
repr(value))

        return value

    def get_prep_value(self, value):
        if isinstance(value, netaddr.EUI):
            value.dialect = netaddr.strategy.eui48.mac_bare
            value = '%s' % value
        return unicode(value)

#------8<----{ models.py }---->8------#
 
# [...]

class Machine(models.Model):
    """Une machine"""
    proprietaire = models.ForeignKey(User)
    batiment = models.ForeignKey(Batiment)
    nom = models.CharField(max_length=64)
    ip = fields.IPAddressField()
    mac = fields.MACAddressField()
    creation = models.DateTimeField(default=timezone.now)
    expiration = models.DateTimeField(default=lambda: timezone.now() + 
datetime.timedelta(days=90))

    @classmethod
    def validmachines(cls):
        """Machines valides actuellement"""
        return cls.objects.filter(expiration__gte=timezone.now())

    def clean(self):
        """Validation du modèle"""
        # Validation Nom de machine
        nom = self.nom.lower()
        if not re.match(r"^[a-z0-9][a-z0-9-]{,63}$", nom):
            raise ValidationError(u"Le nom de machine ne peut contenir que des 
caractères alphanumériques et des tirets")
        same_name = self.validmachines().filter(nom=nom)
        if self.pk:
            same_name = same_name.exclude(pk=self.pk)
        if same_name:
            raise ValidationError(u"Nom de machine déjà utilisé")
        self.nom = nom

        # Validation adresse IP
        if self.ip:
            for net in Subnet.objects.filter(batiment = self.batiment).all():
                if self.ip in net.net:
                    break
            else:
                raise ValidationError(u"Adresse IP hors des réseaux du 
bâtiment")

            same_ip = self.validmachines().filter(ip=self.ip)
            if self.pk:
                same_ip = same_ip.exclude(pk=self.pk)
            if same_ip:
                raise ValidationError(u"Adresse IP en cours d'utilisation")

    def __unicode__(self):
        expire = u""
        if self.expiration <= timezone.now():
            expire = u", expire"
        return u"""<Machine(%s, %s%s)>""" % (self.nom, self.ip, expire)

#------8<-------->8------#

Thanks in advance for any hints,
-- 
Nicolas Dandrimont

BOFH excuse #302:
microelectronic Riemannian curved-space fault in write-only file system

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com.
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.

Reply via email to