mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-25 00:36:11 -06:00
Fix missing NestedSerializer.
This commit is contained in:
parent
04af1e12b2
commit
b78eebed31
@ -45,6 +45,7 @@ __all__ = [
|
||||
'NestedSiteSerializer',
|
||||
'NestedSiteGroupSerializer',
|
||||
'NestedVirtualChassisSerializer',
|
||||
'NestedVirtualDeviceContextSerializer',
|
||||
]
|
||||
|
||||
|
||||
@ -466,3 +467,12 @@ class NestedPowerFeedSerializer(WritableNestedSerializer):
|
||||
class Meta:
|
||||
model = models.PowerFeed
|
||||
fields = ['id', 'url', 'display', 'name', 'cable', '_occupied']
|
||||
|
||||
|
||||
class NestedVirtualDeviceContextSerializer(WritableNestedSerializer):
|
||||
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:virtualdevicecontext-detail')
|
||||
device = NestedDeviceSerializer()
|
||||
|
||||
class Meta:
|
||||
model = models.VirtualDeviceContext
|
||||
fields = ['id', 'url', 'display', 'name', 'identifier', 'device', 'vdc_type']
|
||||
|
@ -317,6 +317,7 @@ class DeviceTypeSerializer(NetBoxModelSerializer):
|
||||
)
|
||||
subdevice_role = ChoiceField(choices=SubdeviceRoleChoices, allow_blank=True, required=False)
|
||||
airflow = ChoiceField(choices=DeviceAirflowChoices, allow_blank=True, required=False)
|
||||
vdc_type = ChoiceField(choices=VirtualDeviceContextTypeChoices, allow_blank=True, required=False)
|
||||
weight_unit = ChoiceField(choices=WeightUnitChoices, allow_blank=True, required=False)
|
||||
device_count = serializers.IntegerField(read_only=True)
|
||||
|
||||
@ -324,8 +325,8 @@ class DeviceTypeSerializer(NetBoxModelSerializer):
|
||||
model = DeviceType
|
||||
fields = [
|
||||
'id', 'url', 'display', 'manufacturer', 'model', 'slug', 'part_number', 'u_height', 'is_full_depth',
|
||||
'subdevice_role', 'airflow', 'weight', 'weight_unit', 'front_image', 'rear_image', 'comments', 'tags',
|
||||
'custom_fields', 'created', 'last_updated', 'device_count',
|
||||
'subdevice_role', 'vdc_type', 'airflow', 'weight', 'weight_unit', 'front_image', 'rear_image', 'comments',
|
||||
'tags', 'custom_fields', 'created', 'last_updated', 'device_count',
|
||||
]
|
||||
|
||||
|
||||
@ -840,6 +841,11 @@ class PowerPortSerializer(NetBoxModelSerializer, CabledObjectSerializer, Connect
|
||||
class InterfaceSerializer(NetBoxModelSerializer, CabledObjectSerializer, ConnectedEndpointsSerializer):
|
||||
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:interface-detail')
|
||||
device = NestedDeviceSerializer()
|
||||
vdcs = NestedVirtualDeviceContextSerializer(
|
||||
required=False,
|
||||
allow_null=True,
|
||||
many=True
|
||||
)
|
||||
module = ComponentNestedModuleSerializer(
|
||||
required=False,
|
||||
allow_null=True
|
||||
@ -876,13 +882,13 @@ class InterfaceSerializer(NetBoxModelSerializer, CabledObjectSerializer, Connect
|
||||
class Meta:
|
||||
model = Interface
|
||||
fields = [
|
||||
'id', 'url', 'display', 'device', 'module', 'name', 'label', 'type', 'enabled', 'parent', 'bridge', 'lag',
|
||||
'mtu', 'mac_address', 'speed', 'duplex', 'wwn', 'mgmt_only', 'description', 'mode', 'rf_role', 'rf_channel',
|
||||
'poe_mode', 'poe_type', 'rf_channel_frequency', 'rf_channel_width', 'tx_power', 'untagged_vlan',
|
||||
'tagged_vlans', 'mark_connected', 'cable', 'cable_end', 'wireless_link', 'link_peers', 'link_peers_type',
|
||||
'wireless_lans', 'vrf', 'l2vpn_termination', 'connected_endpoints', 'connected_endpoints_type',
|
||||
'connected_endpoints_reachable', 'tags', 'custom_fields', 'created', 'last_updated', 'count_ipaddresses',
|
||||
'count_fhrp_groups', '_occupied',
|
||||
'id', 'url', 'display', 'device', 'vdcs', 'module', 'name', 'label', 'type', 'enabled', 'parent', 'bridge',
|
||||
'lag', 'mtu', 'mac_address', 'speed', 'duplex', 'wwn', 'mgmt_only', 'description', 'mode', 'rf_role',
|
||||
'rf_channel', 'poe_mode', 'poe_type', 'rf_channel_frequency', 'rf_channel_width', 'tx_power',
|
||||
'untagged_vlan', 'tagged_vlans', 'mark_connected', 'cable', 'cable_end', 'wireless_link', 'link_peers',
|
||||
'link_peers_type', 'wireless_lans', 'vrf', 'l2vpn_termination', 'connected_endpoints',
|
||||
'connected_endpoints_type', 'connected_endpoints_reachable', 'tags', 'custom_fields', 'created',
|
||||
'last_updated', 'count_ipaddresses', 'count_fhrp_groups', '_occupied',
|
||||
]
|
||||
|
||||
def validate(self, data):
|
||||
|
@ -397,7 +397,7 @@ class DeviceTypeForm(NetBoxModelForm):
|
||||
model = DeviceType
|
||||
fields = [
|
||||
'manufacturer', 'model', 'slug', 'part_number', 'u_height', 'is_full_depth', 'subdevice_role', 'airflow',
|
||||
'vdc_type', 'vdc_type', 'weight', 'weight_unit', 'front_image', 'rear_image', 'comments', 'tags',
|
||||
'vdc_type', 'weight', 'weight_unit', 'front_image', 'rear_image', 'comments', 'tags',
|
||||
]
|
||||
widgets = {
|
||||
'airflow': StaticSelect(),
|
||||
@ -1375,7 +1375,7 @@ class PowerOutletForm(ModularDeviceComponentForm):
|
||||
|
||||
|
||||
class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm):
|
||||
vdc = DynamicModelMultipleChoiceField(
|
||||
vdcs = DynamicModelMultipleChoiceField(
|
||||
queryset=VirtualDeviceContext.objects.all(),
|
||||
required=False,
|
||||
label='Virtual Device Contexts',
|
||||
@ -1457,7 +1457,7 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm):
|
||||
)
|
||||
|
||||
fieldsets = (
|
||||
('Interface', ('device', 'module', 'vdc', 'name', 'label', 'type', 'speed', 'duplex', 'description', 'tags')),
|
||||
('Interface', ('device', 'module', 'vdcs', 'name', 'label', 'type', 'speed', 'duplex', 'description', 'tags')),
|
||||
('Addressing', ('vrf', 'mac_address', 'wwn')),
|
||||
('Operation', ('mtu', 'tx_power', 'enabled', 'mgmt_only', 'mark_connected')),
|
||||
('Related Interfaces', ('parent', 'bridge', 'lag')),
|
||||
@ -1471,7 +1471,7 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm):
|
||||
class Meta:
|
||||
model = Interface
|
||||
fields = [
|
||||
'device', 'module', 'vdc', 'name', 'label', 'type', 'speed', 'duplex', 'enabled', 'parent', 'bridge', 'lag',
|
||||
'device', 'module', 'vdcs', 'name', 'label', 'type', 'speed', 'duplex', 'enabled', 'parent', 'bridge', 'lag',
|
||||
'mac_address', 'wwn', 'mtu', 'mgmt_only', 'mark_connected', 'description', 'poe_mode', 'poe_type', 'mode',
|
||||
'rf_role', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width', 'tx_power', 'wireless_lans',
|
||||
'untagged_vlan', 'tagged_vlans', 'vrf', 'tags',
|
||||
@ -1498,9 +1498,9 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm):
|
||||
def clean_vdc(self):
|
||||
device = self.cleaned_data.get('device')
|
||||
if device.device_type.vdc_type not in [VirtualDeviceContextTypeChoices.CISCO_ASA_CONTEXT, VirtualDeviceContextTypeChoices.CISCO_FTD_INSTANCE]\
|
||||
and len(self.cleaned_data.get('vdc')) > 1:
|
||||
and len(self.cleaned_data.get('vdcs')) > 1:
|
||||
raise forms.ValidationError(f"You cannot assign more then 1 VDC for {device.device_type}")
|
||||
return self.cleaned_data.get('vdc')
|
||||
return self.cleaned_data.get('vdcs')
|
||||
|
||||
|
||||
class FrontPortForm(ModularDeviceComponentForm):
|
||||
|
@ -45,7 +45,7 @@ class Migration(migrations.Migration):
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='interface',
|
||||
name='vdc',
|
||||
name='vdcs',
|
||||
field=models.ManyToManyField(related_name='interfaces', to='dcim.virtualdevicecontext'),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
|
@ -531,7 +531,7 @@ class Interface(ModularComponentModel, BaseInterface, CabledObjectModel, PathEnd
|
||||
max_length=100,
|
||||
blank=True
|
||||
)
|
||||
vdc = models.ManyToManyField(
|
||||
vdcs = models.ManyToManyField(
|
||||
to='dcim.VirtualDeviceContext',
|
||||
related_name='interfaces'
|
||||
)
|
||||
|
@ -124,17 +124,17 @@ class DeviceType(NetBoxModel, WeightMixin):
|
||||
help_text='Parent devices house child devices in device bays. Leave blank '
|
||||
'if this device type is neither a parent nor a child.'
|
||||
)
|
||||
airflow = models.CharField(
|
||||
max_length=50,
|
||||
choices=DeviceAirflowChoices,
|
||||
blank=True
|
||||
)
|
||||
vdc_type = models.CharField(
|
||||
max_length=50,
|
||||
blank=True,
|
||||
choices=VirtualDeviceContextTypeChoices,
|
||||
verbose_name='VDC Type'
|
||||
)
|
||||
airflow = models.CharField(
|
||||
max_length=50,
|
||||
choices=DeviceAirflowChoices,
|
||||
blank=True
|
||||
)
|
||||
front_image = models.ImageField(
|
||||
upload_to='devicetype-images',
|
||||
blank=True
|
||||
@ -1217,3 +1217,7 @@ class VirtualDeviceContext(NetBoxModel):
|
||||
return self.primary_ip4
|
||||
else:
|
||||
return None
|
||||
|
||||
@property
|
||||
def vdc_type(self):
|
||||
return self.device.device_type.vdc_type
|
||||
|
@ -127,13 +127,13 @@ def nullify_connected_endpoints(instance, **kwargs):
|
||||
cablepath.retrace()
|
||||
|
||||
|
||||
@receiver(m2m_changed, sender=Interface.vdc.through)
|
||||
@receiver(m2m_changed, sender=Interface.vdcs.through)
|
||||
def enforce_vdc_type_restrictions(instance, **kwargs):
|
||||
if 'action' == 'post_add':
|
||||
device = instance.device
|
||||
if device.device_type.vdc_type not in [VirtualDeviceContextTypeChoices.CISCO_ASA_CONTEXT, VirtualDeviceContextTypeChoices.CISCO_FTD_INSTANCE] \
|
||||
and len(instance.vdc) > 1:
|
||||
and len(instance.vdcs) > 1:
|
||||
print('Error')
|
||||
raise forms.ValidationError({
|
||||
'vdc': f"You cannot assign more then 1 VDC for {device.device_type}"
|
||||
'vdcs': f"You cannot assign more then 1 VDC for {device.device_type}"
|
||||
})
|
||||
|
@ -57,6 +57,12 @@
|
||||
{{ object.get_airflow_display|placeholder }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>VDC Type</td>
|
||||
<td>
|
||||
{{ object.get_vdc_type_display|placeholder }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Front Image</td>
|
||||
<td>
|
||||
|
@ -36,6 +36,11 @@
|
||||
<th scope="row">Identifier</th>
|
||||
<td>{{ object.identifier|placeholder }}</td>
|
||||
</tr>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">VDC Type</th>
|
||||
<td>{{ object.device.device_type.get_vdc_type_display |placeholder }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Primary IPv4</th>
|
||||
<td>
|
||||
|
Loading…
Reference in New Issue
Block a user