Login

Tuned IPAddressField with IPv4 & IPv6 support

Author:
diverman
Posted:
March 20, 2009
Language:
Python
Version:
1.0
Tags:
field model decimal ipy custom ipv6 ipaddress ip ip-addresses ipv4 ip-address custom-field
Score:
3 (after 3 ratings)

Tuned IPAddressField with IPv4 & IPv6 support

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
"""
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)

More like this

  1. Tuned IPAddressField with IPv4 & IPv6 support using Postgres Network Field type by illsci 5 years, 11 months ago
  2. MAC address field by diverman 6 years, 1 month ago
  3. Storing IP address ModelField as Integer, without nasty hacks.. by sleepycal 3 years, 8 months ago
  4. Test IP against IP address+Subnet whitelist by mtigas 5 years, 8 months ago
  5. Scan uploaded file for viruses with clamav by uandt 6 years, 10 months ago

Comments

jono (on October 30, 2010):

Great snippet!

Instead of "return None" I'd "return IP(0)" just in case you need to compare the results with another IP instance. IPy doesn't like comparing IP's with non IP objects (like None or a string).

#

Please login first before commenting.