Login

Tuned IPAddressField with IPv4 & IPv6 support

Author:
diverman
Posted:
March 20, 2009
Language:
Python
Version:
1.0
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. Template tag - list punctuation for a list of items by shapiromatron 8 months, 3 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 9 months ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 3 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 4 months ago
  5. Help text hyperlinks by sa2812 1 year, 5 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.