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+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment