- Author:
- SeniorHuevo
- Posted:
- March 17, 2010
- Language:
- Python
- Version:
- 1.1
- Score:
- 1 (after 1 ratings)
Based on #1381
Use this piece of code to add IPv4/IPv6 and network support to Django.
An IPAddressField allows you to find IP's for a given subnet. An IPNetworkField allows you to find a subnet for a given IP or find a subnet within a subnet.
For starters, simply paste it into a new file in your app called fields.py.
IPAddressField example
# models.py
from fields import IPAddressField
class IPTest(models.Model):
ip = IPAddressField()
To search for an IP within a given subnet
from ipaddr import IPNetwork
IPTest.objects.filter(ip__in=IPNetwork('10.0.0.0/24'))
IPNetworkField example
# models.py
from fields import IPNetworkField, IPNetworkQuerySet
class IPTest(models.Model):
objects = IPNetworkQuerySet.as_manager()
network = IPNetworkField()
To search for a subnet with a given IP
from ipaddr import IPAddress
IPTest.objects.network('network', IPAddress('10.0.0.1'))
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 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | from ipaddr import _IPAddrBase, IPAddress, IPNetwork
from django.forms import ValidationError as FormValidationError
from django.core.exceptions import ValidationError
from django.forms import fields, widgets
from django.db import models
class IPNetworkWidget(widgets.TextInput):
def render(self, name, value, attrs=None):
if isinstance(value, _IPAddrBase):
value = u'%s' % value
return super(IPNetworkWidget, self).render(name, value, attrs)
class IPNetworkManager(models.Manager):
use_for_related_fields = True
def __init__(self, qs_class=models.query.QuerySet):
self.queryset_class = qs_class
super(IPNetworkManager, self).__init__()
def get_query_set(self):
return self.queryset_class(self.model)
def __getattr__(self, attr, *args):
try:
return getattr(self.__class__, attr, *args)
except AttributeError:
return getattr(self.get_query_set(), attr, *args)
class IPNetworkQuerySet(models.query.QuerySet):
net = None
def network(self, key, value):
if not isinstance(value, _IPAddrBase):
value = IPNetwork(value)
self.net = (key, value)
return self
def iterator(self):
for obj in super(IPNetworkQuerySet, self).iterator():
try:
net = IPNetwork(getattr(obj, self.net[0]))
except (ValueError, TypeError):
pass
else:
if not self.net[1] in net:
continue
yield obj
@classmethod
def as_manager(cls, ManagerClass=IPNetworkManager):
return ManagerClass(cls)
class IPNetworkField(models.Field):
__metaclass__ = models.SubfieldBase
description = "IP Network Field with CIDR support"
empty_strings_allowed = False
def db_type(self, connection):
return 'varchar(45)'
def to_python(self, value):
if not value:
return None
if isinstance(value, _IPAddrBase):
return value
try:
return IPNetwork(value.encode('latin-1'))
except Exception, e:
raise ValidationError(e)
def get_prep_lookup(self, lookup_type, value):
if lookup_type == 'exact':
return self.get_prep_value(value)
elif lookup_type == 'in':
return [self.get_prep_value(v) for v in value]
else:
raise TypeError('Lookup type %r not supported.' \
% lookup_type)
def get_prep_value(self, value):
if isinstance(value, _IPAddrBase):
value = '%s' % value
return unicode(value)
def formfield(self, **kwargs):
defaults = {
'form_class' : fields.CharField,
'widget': IPNetworkWidget,
}
defaults.update(kwargs)
return super(IPNetworkField, self).formfield(**defaults)
class IPAddressField(models.Field):
__metaclass__ = models.SubfieldBase
description = "IP Address Field with IPv6 support"
def db_type(self, connection):
return 'varchar(42)'
def to_python(self, value):
if not value:
return None
if isinstance(value, _IPAddrBase):
return value
try:
return IPAddress(value.encode('latin-1'))
except Exception, e:
raise ValidationError(e)
def get_prep_lookup(self, lookup_type, value):
if lookup_type == 'exact':
return self.get_prep_value(value)
elif lookup_type == 'in':
return [self.get_prep_value(v) for v in value]
else:
raise TypeError('Lookup type %r not supported.' \
% lookup_type)
def get_prep_value(self, value):
if isinstance(value, _IPAddrBase):
value = '%s' % value
return unicode(value)
def formfield(self, **kwargs):
defaults = {
'form_class' : fields.CharField,
'widget': IPNetworkWidget,
}
defaults.update(kwargs)
return super(IPAddressField, self).formfield(**defaults)
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
- Help text hyperlinks by sa2812 1 year, 7 months ago
Comments
Please login first before commenting.