| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061 |
- from django import forms
- from django.core.exceptions import ValidationError
- from django.core.validators import validate_ipv4_address, validate_ipv6_address
- from django.utils.translation import gettext_lazy as _
- from netaddr import IPAddress, IPNetwork, AddrFormatError
- #
- # Form fields
- #
- class IPAddressFormField(forms.Field):
- default_error_messages = {
- 'invalid': _("Enter a valid IPv4 or IPv6 address (without a mask)."),
- }
- def to_python(self, value):
- if not value:
- return None
- if isinstance(value, IPAddress):
- return value
- # netaddr is a bit too liberal with what it accepts as a valid IP address. For example, '1.2.3' will become
- # IPAddress('1.2.0.3'). Here, we employ Django's built-in IPv4 and IPv6 address validators as a sanity check.
- try:
- validate_ipv4_address(value)
- except ValidationError:
- try:
- validate_ipv6_address(value)
- except ValidationError:
- raise ValidationError(_("Invalid IPv4/IPv6 address format: {address}").format(address=value))
- try:
- return IPAddress(value)
- except ValueError:
- raise ValidationError(_('This field requires an IP address without a mask.'))
- except AddrFormatError:
- raise ValidationError(_("Please specify a valid IPv4 or IPv6 address."))
- class IPNetworkFormField(forms.Field):
- default_error_messages = {
- 'invalid': _("Enter a valid IPv4 or IPv6 address (with CIDR mask)."),
- }
- def to_python(self, value):
- if not value:
- return None
- if isinstance(value, IPNetwork):
- return value
- # Ensure that a subnet mask has been specified. This prevents IPs from defaulting to a /32 or /128.
- if len(value.split('/')) != 2:
- raise ValidationError(_('CIDR mask (e.g. /24) is required.'))
- try:
- return IPNetwork(value)
- except AddrFormatError:
- raise ValidationError(_("Please specify a valid IPv4 or IPv6 address."))
|