diff --git a/docs/models/dcim/devicerole.md b/docs/models/dcim/devicerole.md index 786170f2b..3b4c2c012 100644 --- a/docs/models/dcim/devicerole.md +++ b/docs/models/dcim/devicerole.md @@ -12,6 +12,10 @@ A unique human-friendly name. A unique URL-friendly identifier. (This value can be used for filtering.) +### Group + +The [device role group](./devicerolegroup.md) to which this device role belongs (if any). + ### Color The color used when displaying the role in the NetBox UI. diff --git a/netbox/dcim/api/serializers_/roles.py b/netbox/dcim/api/serializers_/roles.py index a066b69df..8167eb898 100644 --- a/netbox/dcim/api/serializers_/roles.py +++ b/netbox/dcim/api/serializers_/roles.py @@ -28,6 +28,7 @@ class DeviceRoleGroupSerializer(NestedGroupModelSerializer): class DeviceRoleSerializer(NetBoxModelSerializer): config_template = ConfigTemplateSerializer(nested=True, required=False, allow_null=True, default=None) + group = DeviceRoleGroupSerializer(nested=True, required=False, allow_null=True, default=None) # Related object counts device_count = RelatedObjectCountField('devices') @@ -36,7 +37,7 @@ class DeviceRoleSerializer(NetBoxModelSerializer): class Meta: model = DeviceRole fields = [ - 'id', 'url', 'display_url', 'display', 'name', 'slug', 'color', 'vm_role', 'config_template', + 'id', 'url', 'display_url', 'display', 'name', 'slug', 'color', 'group', 'vm_role', 'config_template', 'description', 'tags', 'custom_fields', 'created', 'last_updated', 'device_count', 'virtualmachine_count', ] brief_fields = ('id', 'url', 'display', 'name', 'slug', 'description', 'device_count', 'virtualmachine_count') diff --git a/netbox/dcim/filtersets.py b/netbox/dcim/filtersets.py index 0092d3655..9e590b2bd 100644 --- a/netbox/dcim/filtersets.py +++ b/netbox/dcim/filtersets.py @@ -953,6 +953,19 @@ class DeviceRoleFilterSet(OrganizationalModelFilterSet): queryset=ConfigTemplate.objects.all(), label=_('Config template (ID)'), ) + group_id = TreeNodeMultipleChoiceFilter( + queryset=DeviceRoleGroup.objects.all(), + field_name='group', + lookup_expr='in', + label=_('Device role group (ID)'), + ) + group = TreeNodeMultipleChoiceFilter( + queryset=DeviceRoleGroup.objects.all(), + field_name='group', + lookup_expr='in', + to_field_name='slug', + label=_('Device role group (slug)'), + ) class Meta: model = DeviceRole diff --git a/netbox/dcim/forms/bulk_edit.py b/netbox/dcim/forms/bulk_edit.py index a14074512..aec52d286 100644 --- a/netbox/dcim/forms/bulk_edit.py +++ b/netbox/dcim/forms/bulk_edit.py @@ -634,6 +634,11 @@ class DeviceRoleBulkEditForm(NetBoxModelBulkEditForm): label=_('Color'), required=False ) + group = DynamicModelChoiceField( + label=_('Group'), + queryset=DeviceRoleGroup.objects.all(), + required=False + ) vm_role = forms.NullBooleanField( required=False, widget=BulkEditNullBooleanSelect, @@ -652,9 +657,9 @@ class DeviceRoleBulkEditForm(NetBoxModelBulkEditForm): model = DeviceRole fieldsets = ( - FieldSet('color', 'vm_role', 'config_template', 'description'), + FieldSet('color', 'group', 'vm_role', 'config_template', 'description'), ) - nullable_fields = ('color', 'config_template', 'description') + nullable_fields = ('color', 'group', 'config_template', 'description') class PlatformBulkEditForm(NetBoxModelBulkEditForm): diff --git a/netbox/dcim/forms/bulk_import.py b/netbox/dcim/forms/bulk_import.py index 9f84ea22e..8fd8a5751 100644 --- a/netbox/dcim/forms/bulk_import.py +++ b/netbox/dcim/forms/bulk_import.py @@ -483,11 +483,18 @@ class DeviceRoleImportForm(NetBoxModelImportForm): required=False, help_text=_('Config template') ) + group = CSVModelChoiceField( + label=_('Group'), + queryset=DeviceRoleGroup.objects.all(), + required=False, + to_field_name='name', + help_text=_('Assigned group') + ) slug = SlugField() class Meta: model = DeviceRole - fields = ('name', 'slug', 'color', 'vm_role', 'config_template', 'description', 'tags') + fields = ('name', 'slug', 'group', 'color', 'vm_role', 'config_template', 'description', 'tags') class PlatformImportForm(NetBoxModelImportForm): diff --git a/netbox/dcim/forms/filtersets.py b/netbox/dcim/forms/filtersets.py index 07764f023..1d0e0480f 100644 --- a/netbox/dcim/forms/filtersets.py +++ b/netbox/dcim/forms/filtersets.py @@ -700,6 +700,12 @@ class DeviceRoleFilterForm(NetBoxModelFilterSetForm): required=False, label=_('Config template') ) + group_id = DynamicModelMultipleChoiceField( + queryset=DeviceRoleGroup.objects.all(), + required=False, + null_option='None', + label=_('Group') + ) tag = TagFilterField(model) diff --git a/netbox/dcim/forms/model_forms.py b/netbox/dcim/forms/model_forms.py index ae184389c..9984afc7b 100644 --- a/netbox/dcim/forms/model_forms.py +++ b/netbox/dcim/forms/model_forms.py @@ -450,18 +450,23 @@ class DeviceRoleForm(NetBoxModelForm): queryset=ConfigTemplate.objects.all(), required=False ) + group = DynamicModelChoiceField( + label=_('Group'), + queryset=DeviceRoleGroup.objects.all(), + required=False + ) slug = SlugField() fieldsets = ( FieldSet( - 'name', 'slug', 'color', 'vm_role', 'config_template', 'description', 'tags', name=_('Device Role') + 'name', 'slug', 'group', 'color', 'vm_role', 'config_template', 'description', 'tags', name=_('Device Role') ), ) class Meta: model = DeviceRole fields = [ - 'name', 'slug', 'color', 'vm_role', 'config_template', 'description', 'tags', + 'name', 'slug', 'group', 'color', 'vm_role', 'config_template', 'description', 'tags', ] diff --git a/netbox/dcim/models/devices.py b/netbox/dcim/models/devices.py index 4c37d2124..f9db72585 100644 --- a/netbox/dcim/models/devices.py +++ b/netbox/dcim/models/devices.py @@ -522,6 +522,10 @@ class DeviceRole(OrganizationalModel): null=True ) + clone_fields = ( + 'group', 'description', + ) + class Meta: ordering = ('name',) verbose_name = _('device role') diff --git a/netbox/dcim/tables/devices.py b/netbox/dcim/tables/devices.py index cc99188ca..7919ef449 100644 --- a/netbox/dcim/tables/devices.py +++ b/netbox/dcim/tables/devices.py @@ -90,6 +90,10 @@ class DeviceRoleTable(NetBoxTable): verbose_name=_('Name'), linkify=True ) + group = tables.Column( + verbose_name=_('Group'), + linkify=True + ) device_count = columns.LinkedCountColumn( viewname='dcim:device_list', url_params={'role_id': 'pk'}, @@ -115,10 +119,10 @@ class DeviceRoleTable(NetBoxTable): class Meta(NetBoxTable.Meta): model = models.DeviceRole fields = ( - 'pk', 'id', 'name', 'device_count', 'vm_count', 'color', 'vm_role', 'config_template', 'description', - 'slug', 'tags', 'actions', 'created', 'last_updated', + 'pk', 'id', 'name', 'group', 'device_count', 'vm_count', 'color', 'vm_role', + 'config_template', 'description', 'slug', 'tags', 'actions', 'created', 'last_updated', ) - default_columns = ('pk', 'name', 'device_count', 'vm_count', 'color', 'vm_role', 'description') + default_columns = ('pk', 'name', 'group', 'device_count', 'vm_count', 'color', 'vm_role', 'description') # diff --git a/netbox/templates/dcim/devicerole.html b/netbox/templates/dcim/devicerole.html index d9e170af3..59f5ff5a3 100644 --- a/netbox/templates/dcim/devicerole.html +++ b/netbox/templates/dcim/devicerole.html @@ -26,6 +26,10 @@
{% trans "Name" %} | +{{ object.name }} | +
---|---|
{% trans "Description" %} | +{{ object.description|placeholder }} | +
{% trans "Parent" %} | +{{ object.parent|linkify|placeholder }} | +