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.