Coverage for ipam/formfields.py: 23%
38 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 18:35 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 18:35 +0000
1from django import forms
2from django.core.exceptions import ValidationError
3from django.core.validators import validate_ipv4_address, validate_ipv6_address
4from django.utils.translation import gettext_lazy as _
5from netaddr import AddrFormatError, IPAddress, IPNetwork
7#
8# Form fields
9#
12class IPAddressFormField(forms.Field):
13 default_error_messages = {
14 'invalid': _("Enter a valid IPv4 or IPv6 address (without a mask)."),
15 }
17 def to_python(self, value):
18 if not value:
19 return None
21 if isinstance(value, IPAddress):
22 return value
24 # netaddr is a bit too liberal with what it accepts as a valid IP address. For example, '1.2.3' will become
25 # IPAddress('1.2.0.3'). Here, we employ Django's built-in IPv4 and IPv6 address validators as a sanity check.
26 try:
27 validate_ipv4_address(value)
28 except ValidationError:
29 try:
30 validate_ipv6_address(value)
31 except ValidationError:
32 raise ValidationError(_("Invalid IPv4/IPv6 address format: {address}").format(address=value))
34 try:
35 return IPAddress(value)
36 except ValueError:
37 raise ValidationError(_('This field requires an IP address without a mask.'))
38 except AddrFormatError:
39 raise ValidationError(_("Please specify a valid IPv4 or IPv6 address."))
42class IPNetworkFormField(forms.Field):
43 default_error_messages = {
44 'invalid': _("Enter a valid IPv4 or IPv6 address (with CIDR mask)."),
45 }
47 def to_python(self, value):
48 if not value:
49 return None
51 if isinstance(value, IPNetwork):
52 return value
54 # Ensure that a subnet mask has been specified. This prevents IPs from defaulting to a /32 or /128.
55 if len(value.split('/')) != 2:
56 raise ValidationError(_('CIDR mask (e.g. /24) is required.'))
58 try:
59 return IPNetwork(value)
60 except AddrFormatError:
61 raise ValidationError(_("Please specify a valid IPv4 or IPv6 address."))