From 91e546c8001aba28c2e303393b36fa8fd8c280e2 Mon Sep 17 00:00:00 2001 From: Arthur Date: Tue, 18 Apr 2023 08:55:09 -0700 Subject: [PATCH] #12278 add serializer for ipaddressfield to remove spectacular warnings --- netbox/ipam/api/serializers.py | 16 ++++++++++++++++ netbox/ipam/validators.py | 11 +++++++++++ 2 files changed, 27 insertions(+) diff --git a/netbox/ipam/api/serializers.py b/netbox/ipam/api/serializers.py index 10c27b252..220bafa8e 100644 --- a/netbox/ipam/api/serializers.py +++ b/netbox/ipam/api/serializers.py @@ -1,4 +1,5 @@ from django.contrib.contenttypes.models import ContentType +from django.utils.translation import gettext_lazy as _ from drf_spectacular.utils import extend_schema_field from rest_framework import serializers @@ -6,6 +7,8 @@ from dcim.api.nested_serializers import NestedDeviceSerializer, NestedSiteSerial from ipam.choices import * from ipam.constants import IPADDRESS_ASSIGNMENT_MODELS, VLANGROUP_SCOPE_TYPES from ipam.models import * +from ipam.validators import validate_ipaddress_with_mask +from netaddr import AddrFormatError, IPNetwork from netbox.api.fields import ChoiceField, ContentTypeField, SerializedPKRelatedField from netbox.api.serializers import NetBoxModelSerializer from netbox.constants import NESTED_SERIALIZER_PREFIX @@ -387,10 +390,23 @@ class IPRangeSerializer(NetBoxModelSerializer): # # IP addresses # +class IPAddressField(serializers.CharField): + """IPAddressField with mask""" + + default_error_messages = { + 'invalid': _('Enter a valid IPv4 or IPv6 address with optional mask.'), + } + + def __init__(self, **kwargs): + super().__init__(**kwargs) + validator = validate_ipaddress_with_mask + self.validators.append(validator) + class IPAddressSerializer(NetBoxModelSerializer): url = serializers.HyperlinkedIdentityField(view_name='ipam-api:ipaddress-detail') family = ChoiceField(choices=IPAddressFamilyChoices, read_only=True) + address = IPAddressField() vrf = NestedVRFSerializer(required=False, allow_null=True) tenant = NestedTenantSerializer(required=False, allow_null=True) status = ChoiceField(choices=IPAddressStatusChoices, required=False) diff --git a/netbox/ipam/validators.py b/netbox/ipam/validators.py index 50faea8b8..b8e36c5d2 100644 --- a/netbox/ipam/validators.py +++ b/netbox/ipam/validators.py @@ -1,5 +1,6 @@ from django.core.exceptions import ValidationError from django.core.validators import BaseValidator, RegexValidator +from netaddr import AddrFormatError, IPNetwork def prefix_validator(prefix): @@ -28,3 +29,13 @@ DNSValidator = RegexValidator( message='Only alphanumeric characters, asterisks, hyphens, periods, and underscores are allowed in DNS names', code='invalid' ) + + +def validate_ipaddress_with_mask(address): + if address: + try: + IPNetwork(address) + except AddrFormatError: + raise ValidationError("Invalid IP address format: {}".format(address)) + except (TypeError, ValueError) as e: + raise ValidationError(e)