12278 add ipaddressfield serializer for OpenAPI spectacular typing (#12285)

* #12278 add serializer for ipaddressfield to remove spectacular warnings

* #12278 add ipaddressfieldserializer to nested serializers

* #12278 fix to_internal_value to_representation in serializer

* #12278 to_internal_value is called before validation! need to raise validation error if incorrect format

* #12278 to_internal_value needs to return value doh

* #12278 move IPAddressField to field_serializers

* #12278 remove old import

* 12278 remove validator
This commit is contained in:
Arthur Hanson 2023-04-21 09:41:03 -07:00 committed by GitHub
parent 15d80f4e1b
commit 55385dd0db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 40 additions and 0 deletions

View File

@ -0,0 +1,32 @@
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from ipam import models
from netaddr import AddrFormatError, IPNetwork
__all__ = [
'IPAddressField',
]
#
# IP address field
#
class IPAddressField(serializers.CharField):
"""IPAddressField with mask"""
default_error_messages = {
'invalid': _('Enter a valid IPv4 or IPv6 address with optional mask.'),
}
def to_internal_value(self, data):
try:
return IPNetwork(data)
except AddrFormatError:
raise serializers.ValidationError("Invalid IP address format: {}".format(data))
except (TypeError, ValueError) as e:
raise serializers.ValidationError(e)
def to_representation(self, value):
return str(value)

View File

@ -4,6 +4,7 @@ from rest_framework import serializers
from ipam import models from ipam import models
from ipam.models.l2vpn import L2VPNTermination, L2VPN from ipam.models.l2vpn import L2VPNTermination, L2VPN
from netbox.api.serializers import WritableNestedSerializer from netbox.api.serializers import WritableNestedSerializer
from .field_serializers import IPAddressField
__all__ = [ __all__ = [
'NestedAggregateSerializer', 'NestedAggregateSerializer',
@ -182,6 +183,8 @@ class NestedPrefixSerializer(WritableNestedSerializer):
class NestedIPRangeSerializer(WritableNestedSerializer): class NestedIPRangeSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:iprange-detail') url = serializers.HyperlinkedIdentityField(view_name='ipam-api:iprange-detail')
family = serializers.IntegerField(read_only=True) family = serializers.IntegerField(read_only=True)
start_address = IPAddressField()
end_address = IPAddressField()
class Meta: class Meta:
model = models.IPRange model = models.IPRange
@ -195,6 +198,7 @@ class NestedIPRangeSerializer(WritableNestedSerializer):
class NestedIPAddressSerializer(WritableNestedSerializer): class NestedIPAddressSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:ipaddress-detail') url = serializers.HyperlinkedIdentityField(view_name='ipam-api:ipaddress-detail')
family = serializers.IntegerField(read_only=True) family = serializers.IntegerField(read_only=True)
address = IPAddressField()
class Meta: class Meta:
model = models.IPAddress model = models.IPAddress

View File

@ -13,6 +13,7 @@ from tenancy.api.nested_serializers import NestedTenantSerializer
from utilities.api import get_serializer_for_model from utilities.api import get_serializer_for_model
from virtualization.api.nested_serializers import NestedVirtualMachineSerializer from virtualization.api.nested_serializers import NestedVirtualMachineSerializer
from .nested_serializers import * from .nested_serializers import *
from .field_serializers import IPAddressField
# #
@ -369,6 +370,8 @@ class AvailablePrefixSerializer(serializers.Serializer):
class IPRangeSerializer(NetBoxModelSerializer): class IPRangeSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:iprange-detail') url = serializers.HyperlinkedIdentityField(view_name='ipam-api:iprange-detail')
family = ChoiceField(choices=IPAddressFamilyChoices, read_only=True) family = ChoiceField(choices=IPAddressFamilyChoices, read_only=True)
start_address = IPAddressField()
end_address = IPAddressField()
vrf = NestedVRFSerializer(required=False, allow_null=True) vrf = NestedVRFSerializer(required=False, allow_null=True)
tenant = NestedTenantSerializer(required=False, allow_null=True) tenant = NestedTenantSerializer(required=False, allow_null=True)
status = ChoiceField(choices=IPRangeStatusChoices, required=False) status = ChoiceField(choices=IPRangeStatusChoices, required=False)
@ -391,6 +394,7 @@ class IPRangeSerializer(NetBoxModelSerializer):
class IPAddressSerializer(NetBoxModelSerializer): class IPAddressSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:ipaddress-detail') url = serializers.HyperlinkedIdentityField(view_name='ipam-api:ipaddress-detail')
family = ChoiceField(choices=IPAddressFamilyChoices, read_only=True) family = ChoiceField(choices=IPAddressFamilyChoices, read_only=True)
address = IPAddressField()
vrf = NestedVRFSerializer(required=False, allow_null=True) vrf = NestedVRFSerializer(required=False, allow_null=True)
tenant = NestedTenantSerializer(required=False, allow_null=True) tenant = NestedTenantSerializer(required=False, allow_null=True)
status = ChoiceField(choices=IPAddressStatusChoices, required=False) status = ChoiceField(choices=IPAddressStatusChoices, required=False)