""" IPAddressField for models with IPv4 & IPv6 support Requires: IPy http://software.inl.fr/trac/wiki/IPy http://c0re.23.nu/c0de/IPy/ On Debian/Ubuntu: apt-get install python-ipy Example: class Host(models.Model): hostname = models.CharField() ip = IPAddressField() >>> my_host = Host() >>> my_host.hostname = 'server' >>> my_host.ip = '192.168.0.1' >>> my_host.save() >>> my_host.ip IP('192.168.0.1') >>> my_host.ip = 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff' >>> dir(my_host.ip) ['NoPrefixForSingleIp', 'WantPrefixLen', '__add__', '__cmp__', '__contains__', '__doc__', '__getitem__', '__hash__', '__init__', '__len__', '__module__', '__nonzero__', '__repr__', '__str__', '_ipversion', '_prefixlen', '_printPrefix', 'broadcast', 'int', 'ip', 'iptype', 'len', 'make_net', 'net', 'netmask', 'overlaps', 'prefixlen', 'reverseName', 'reverseNames', 'strBin', 'strCompressed', 'strDec', 'strFullsize', 'strHex', 'strNetmask', 'strNormal', 'version'] >>> my_host.ip.reverseName() 'f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.ip6.arpa.' >>> my_host.ip.version() 6 >>> my_host.ip = '1.2.3.4.5' ValidationError: IPv4 Address with more than 4 bytes >>> my_host.ip = 'aa:dd:xx' ValidationError: 'aa:dd:xx': Invalid IPv6 address: should have 8 hextets """ from django.forms import ValidationError as FormValidationError from django.core.exceptions import ValidationError from django.forms import fields, widgets from django.db import models from decimal import Decimal from IPy import IP IP.__long__ = IP.int def clean_ip(ip): 'Method for validating IPs on forms' try: IP(ip) except Exception, e: raise FormValidationError(e) return ip class IPAddressWidget(widgets.TextInput): def render(self, name, value, attrs=None): if isinstance(value, IP): value = unicode(value) return super(IPAddressWidget, self).render(name, value, attrs) class IPAddressField(models.Field): __metaclass__ = models.SubfieldBase def db_type(self): return 'numeric(39, 0)' def to_python(self, value): if not value: return None elif isinstance(value, Decimal): value = long(value) try: return IP(value) except Exception, e: raise ValidationError(e) def get_db_prep_lookup(self, lookup_type, value): try: if lookup_type in ('range', 'in'): return [self.get_db_prep_value(v) for v in value] return [self.get_db_prep_value(value)] except ValidationError: return super(IPAddressField, self).get_db_prep_lookup(lookup_type, value) def get_db_prep_value(self, value): try: return long(self.to_python(value)) except TypeError: return None def formfield(self, **kwargs): defaults = { 'form_class': fields.CharField, 'widget': IPAddressWidget, } defaults.update(kwargs) return super(IPAddressField, self).formfield(**defaults)