3
from django.core.exceptions import ValidationError
4
from django.forms import forms
5
from django.utils.translation import ugettext as _
7
ip_allowed_symbols_re = re.compile(r'^[a-fA-F0-9:/\.]+$')
12
class IPField(forms.Field):
14
Form field for entering IP/range values, with validation.
15
Supports IPv4/IPv6 in the format:
18
.. ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
19
.. ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/zz
20
and all compressed forms. Also the short forms
25
.. attribute:: version
27
Specifies which IP version to validate,
28
valid values are 1 (fields.IPv4), 2 (fields.IPv6) or
29
both - 3 (fields.IPv4 | fields.IPv6).
34
Boolean flag to validate subnet masks along with IP address.
37
.. attribute:: mask_range_from
38
Subnet range limitation, e.g. 16
39
That means the input mask will be checked to be in the range
40
16:max_value. Useful to limit the subnet ranges
41
to A/B/C-class networks.
43
invalid_format_message = _("Incorrect format for IP address")
44
invalid_version_message = _("Invalid version for IP address")
45
invalid_mask_message = _("Invalid subnet mask")
49
def __init__(self, *args, **kwargs):
50
self.mask = kwargs.pop("mask", None)
51
self.min_mask = kwargs.pop("mask_range_from", 0)
52
self.version = kwargs.pop('version', IPv4)
54
super(IPField, self).__init__(*args, **kwargs)
56
def validate(self, value):
57
super(IPField, self).validate(value)
58
if not value and not self.required:
63
self.ip = netaddr.IPNetwork(value)
65
self.ip = netaddr.IPAddress(value)
67
raise ValidationError(self.invalid_format_message)
69
if not any([self.version & IPv4 > 0 and self.ip.version == 4,
70
self.version & IPv6 > 0 and self.ip.version == 6]):
71
raise ValidationError(self.invalid_version_message)
74
if self.ip.version == 4 and \
75
not self.min_mask <= self.ip.prefixlen <= self.max_v4_mask:
76
raise ValidationError(self.invalid_mask_message)
78
if self.ip.version == 6 and \
79
not self.min_mask <= self.ip.prefixlen <= self.max_v6_mask:
80
raise ValidationError(self.invalid_mask_message)
82
def clean(self, value):
83
super(IPField, self).clean(value)
84
return str(getattr(self, "ip", ""))