1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

DeviceType.subdevice_role to slug (#3569)

This commit is contained in:
Jeremy Stretch
2019-11-18 22:03:25 -05:00
parent fbd12e1887
commit afd82fd9d3
8 changed files with 71 additions and 36 deletions

View File

@ -187,7 +187,7 @@ class ManufacturerSerializer(ValidatedModelSerializer):
class DeviceTypeSerializer(TaggitSerializer, CustomFieldModelSerializer):
manufacturer = NestedManufacturerSerializer()
subdevice_role = ChoiceField(choices=SUBDEVICE_ROLE_CHOICES, required=False, allow_null=True)
subdevice_role = ChoiceField(choices=SubdeviceRoleChoices, required=False, allow_null=True)
tags = TagListSerializerField(required=False)
device_count = serializers.IntegerField(read_only=True)

View File

@ -66,6 +66,26 @@ class RackStatusChoices(ChoiceSet):
}
#
# DeviceTypes
#
class SubdeviceRoleChoices(ChoiceSet):
ROLE_PARENT = 'parent'
ROLE_CHILD = 'child'
CHOICES = (
(ROLE_PARENT, 'Parent'),
(ROLE_CHILD, 'Child'),
)
LEGACY_MAP = {
ROLE_PARENT: True,
ROLE_CHILD: False,
}
#
# Devices
#

View File

@ -1,12 +1,3 @@
# Parent/child device roles
SUBDEVICE_ROLE_PARENT = True
SUBDEVICE_ROLE_CHILD = False
SUBDEVICE_ROLE_CHOICES = (
(None, 'None'),
(SUBDEVICE_ROLE_PARENT, 'Parent'),
(SUBDEVICE_ROLE_CHILD, 'Child'),
)
#
# Numeric interface types
#

View File

@ -879,12 +879,10 @@ class DeviceTypeFilterForm(BootstrapMixin, CustomFieldFilterForm):
value_field="slug",
)
)
subdevice_role = forms.NullBooleanField(
subdevice_role = forms.MultipleChoiceField(
choices=add_blank_choice(SubdeviceRoleChoices),
required=False,
label='Subdevice role',
widget=StaticSelect2(
choices=add_blank_choice(SUBDEVICE_ROLE_CHOICES)
)
widget=StaticSelect2Multiple()
)
console_ports = forms.NullBooleanField(
required=False,
@ -3382,7 +3380,7 @@ class PopulateDeviceBayForm(BootstrapMixin, forms.Form):
rack=device_bay.device.rack,
parent_bay__isnull=True,
device_type__u_height=0,
device_type__subdevice_role=SUBDEVICE_ROLE_CHILD
device_type__subdevice_role=SubdeviceRoleChoices.ROLE_CHILD
).exclude(pk=device_bay.device.pk)

View File

@ -0,0 +1,31 @@
from django.db import migrations, models
SUBDEVICE_ROLE_CHOICES = (
('true', 'parent'),
('false', 'child'),
)
def devicetype_subdevicerole_to_slug(apps, schema_editor):
DeviceType = apps.get_model('dcim', 'DeviceType')
for boolean, slug in SUBDEVICE_ROLE_CHOICES:
DeviceType.objects.filter(subdevice_role=boolean).update(subdevice_role=slug)
class Migration(migrations.Migration):
atomic = False
dependencies = [
('dcim', '0080_device_face_to_slug'),
]
operations = [
migrations.AlterField(
model_name='devicetype',
name='subdevice_role',
field=models.CharField(blank=True, default='', max_length=50),
),
migrations.RunPython(
code=devicetype_subdevicerole_to_slug
),
]

View File

@ -919,12 +919,12 @@ class DeviceType(ChangeLoggedModel, CustomFieldModel):
verbose_name='Is full depth',
help_text='Device consumes both front and rear rack faces'
)
subdevice_role = models.NullBooleanField(
default=None,
subdevice_role = models.CharField(
max_length=50,
choices=SubdeviceRoleChoices,
verbose_name='Parent/child status',
choices=SUBDEVICE_ROLE_CHOICES,
help_text='Parent devices house child devices in device bays. Select '
'"None" if this device type is neither a parent nor a child.'
help_text='Parent devices house child devices in device bays. Leave blank '
'if this device type is neither a parent nor a child.'
)
comments = models.TextField(
blank=True
@ -968,7 +968,7 @@ class DeviceType(ChangeLoggedModel, CustomFieldModel):
self.part_number,
self.u_height,
self.is_full_depth,
self.get_subdevice_role_display() if self.subdevice_role else None,
self.get_subdevice_role_display(),
self.comments,
)
@ -988,13 +988,15 @@ class DeviceType(ChangeLoggedModel, CustomFieldModel):
"{}U".format(d, d.rack, self.u_height)
})
if self.subdevice_role != SUBDEVICE_ROLE_PARENT and self.device_bay_templates.count():
if (
self.subdevice_role != SubdeviceRoleChoices.ROLE_PARENT
) and self.device_bay_templates.count():
raise ValidationError({
'subdevice_role': "Must delete all device bay templates associated with this device before "
"declassifying it as a parent device."
})
if self.u_height and self.subdevice_role == SUBDEVICE_ROLE_CHILD:
if self.u_height and self.subdevice_role == SubdeviceRoleChoices.ROLE_CHILD:
raise ValidationError({
'u_height': "Child device types must be 0U."
})
@ -1005,11 +1007,11 @@ class DeviceType(ChangeLoggedModel, CustomFieldModel):
@property
def is_parent_device(self):
return bool(self.subdevice_role)
return self.subdevice_role == SubdeviceRoleChoices.ROLE_PARENT
@property
def is_child_device(self):
return bool(self.subdevice_role is False)
return self.subdevice_role == SubdeviceRoleChoices.ROLE_CHILD
class ConsolePortTemplate(ComponentTemplateModel):

View File

@ -156,10 +156,6 @@ DEVICE_PRIMARY_IP = """
{{ record.primary_ip4.address.ip|default:"" }}
"""
SUBDEVICE_ROLE_TEMPLATE = """
{% if record.subdevice_role == True %}Parent{% elif record.subdevice_role == False %}Child{% else %}—{% endif %}
"""
DEVICETYPE_INSTANCES_TEMPLATE = """
<a href="{% url 'dcim:device_list' %}?manufacturer_id={{ record.manufacturer_id }}&device_type_id={{ record.pk }}">{{ record.instance_count }}</a>
"""
@ -391,10 +387,6 @@ class DeviceTypeTable(BaseTable):
verbose_name='Device Type'
)
is_full_depth = BooleanColumn(verbose_name='Full Depth')
subdevice_role = tables.TemplateColumn(
template_code=SUBDEVICE_ROLE_TEMPLATE,
verbose_name='Subdevice Role'
)
instance_count = tables.TemplateColumn(
template_code=DEVICETYPE_INSTANCES_TEMPLATE,
verbose_name='Instances'

View File

@ -3,6 +3,7 @@ from netaddr import IPNetwork
from rest_framework import status
from circuits.models import Circuit, CircuitTermination, CircuitType, Provider
from dcim.choices import SubdeviceRoleChoices
from dcim.constants import *
from dcim.models import (
Cable, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay,
@ -2590,11 +2591,11 @@ class DeviceBayTest(APITestCase):
manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
self.devicetype1 = DeviceType.objects.create(
manufacturer=manufacturer, model='Parent Device Type', slug='parent-device-type',
subdevice_role=SUBDEVICE_ROLE_PARENT
subdevice_role=SubdeviceRoleChoices.ROLE_PARENT
)
self.devicetype2 = DeviceType.objects.create(
manufacturer=manufacturer, model='Child Device Type', slug='child-device-type',
subdevice_role=SUBDEVICE_ROLE_CHILD
subdevice_role=SubdeviceRoleChoices.ROLE_CHILD
)
devicerole = DeviceRole.objects.create(
name='Test Device Role 1', slug='test-device-role-1', color='ff0000'