Jelajahi Sumber

Closes #4793: Add description field to device component templates

Jeremy Stretch 5 tahun lalu
induk
melakukan
52a13b1960

+ 2 - 0
docs/release-notes/version-2.9.md

@@ -16,6 +16,7 @@ NetBox v2.9 replaces Django's built-in permissions framework with one that suppo
 * [#4742](https://github.com/netbox-community/netbox/issues/4742) - Add tagging for cables, power panels, and rack reservations
 * [#4788](https://github.com/netbox-community/netbox/issues/4788) - Add dedicated views for all device components
 * [#4792](https://github.com/netbox-community/netbox/issues/4792) - Add bulk rename capability for console and power ports
+* [#4793](https://github.com/netbox-community/netbox/issues/4793) - Add `description` field to device component templates
 * [#4795](https://github.com/netbox-community/netbox/issues/4795) - Add bulk disconnect capability for console and power ports
 
 ### Configuration Changes
@@ -40,6 +41,7 @@ NetBox v2.9 replaces Django's built-in permissions framework with one that suppo
 * The IP address model now uses a generic foreign key to refer to the assigned interface. The `interface` field on the serializer has been replaced with `assigned_object_type` and `assigned_object_id` for write operations. If one exists, the assigned interface is available as `assigned_object`.
 * The serialized representation of a virtual machine interface now includes only relevant fields: `type`, `lag`, `mgmt_only`, `connected_endpoint_type`, `connected_endpoint`, and `cable` are no longer included.
 * dcim.VirtualChassis: Added a mandatory `name` field
+* An optional `description` field has been added to all device component templates
 
 ### Other Changes
 

+ 8 - 8
netbox/dcim/api/serializers.py

@@ -245,7 +245,7 @@ class ConsolePortTemplateSerializer(ValidatedModelSerializer):
 
     class Meta:
         model = ConsolePortTemplate
-        fields = ['id', 'device_type', 'name', 'label', 'type']
+        fields = ['id', 'device_type', 'name', 'label', 'type', 'description']
 
 
 class ConsoleServerPortTemplateSerializer(ValidatedModelSerializer):
@@ -258,7 +258,7 @@ class ConsoleServerPortTemplateSerializer(ValidatedModelSerializer):
 
     class Meta:
         model = ConsoleServerPortTemplate
-        fields = ['id', 'device_type', 'name', 'label', 'type']
+        fields = ['id', 'device_type', 'name', 'label', 'type', 'description']
 
 
 class PowerPortTemplateSerializer(ValidatedModelSerializer):
@@ -271,7 +271,7 @@ class PowerPortTemplateSerializer(ValidatedModelSerializer):
 
     class Meta:
         model = PowerPortTemplate
-        fields = ['id', 'device_type', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw']
+        fields = ['id', 'device_type', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description']
 
 
 class PowerOutletTemplateSerializer(ValidatedModelSerializer):
@@ -292,7 +292,7 @@ class PowerOutletTemplateSerializer(ValidatedModelSerializer):
 
     class Meta:
         model = PowerOutletTemplate
-        fields = ['id', 'device_type', 'name', 'label', 'type', 'power_port', 'feed_leg']
+        fields = ['id', 'device_type', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description']
 
 
 class InterfaceTemplateSerializer(ValidatedModelSerializer):
@@ -301,7 +301,7 @@ class InterfaceTemplateSerializer(ValidatedModelSerializer):
 
     class Meta:
         model = InterfaceTemplate
-        fields = ['id', 'device_type', 'name', 'label', 'type', 'mgmt_only']
+        fields = ['id', 'device_type', 'name', 'label', 'type', 'mgmt_only', 'description']
 
 
 class RearPortTemplateSerializer(ValidatedModelSerializer):
@@ -310,7 +310,7 @@ class RearPortTemplateSerializer(ValidatedModelSerializer):
 
     class Meta:
         model = RearPortTemplate
-        fields = ['id', 'device_type', 'name', 'type', 'positions']
+        fields = ['id', 'device_type', 'name', 'type', 'positions', 'description']
 
 
 class FrontPortTemplateSerializer(ValidatedModelSerializer):
@@ -320,7 +320,7 @@ class FrontPortTemplateSerializer(ValidatedModelSerializer):
 
     class Meta:
         model = FrontPortTemplate
-        fields = ['id', 'device_type', 'name', 'type', 'rear_port', 'rear_port_position']
+        fields = ['id', 'device_type', 'name', 'type', 'rear_port', 'rear_port_position', 'description']
 
 
 class DeviceBayTemplateSerializer(ValidatedModelSerializer):
@@ -328,7 +328,7 @@ class DeviceBayTemplateSerializer(ValidatedModelSerializer):
 
     class Meta:
         model = DeviceBayTemplate
-        fields = ['id', 'device_type', 'name', 'label']
+        fields = ['id', 'device_type', 'name', 'label', 'description']
 
 
 #

+ 39 - 16
netbox/dcim/forms.py

@@ -1053,6 +1053,9 @@ class ComponentTemplateCreateForm(LabeledComponentForm):
             display_field='model'
         )
     )
+    description = forms.CharField(
+        required=False
+    )
 
 
 class ConsolePortTemplateForm(BootstrapMixin, forms.ModelForm):
@@ -1060,7 +1063,7 @@ class ConsolePortTemplateForm(BootstrapMixin, forms.ModelForm):
     class Meta:
         model = ConsolePortTemplate
         fields = [
-            'device_type', 'name', 'label', 'type',
+            'device_type', 'name', 'label', 'type', 'description',
         ]
         widgets = {
             'device_type': forms.HiddenInput(),
@@ -1086,7 +1089,7 @@ class ConsolePortTemplateBulkEditForm(BootstrapMixin, BulkEditForm):
     )
 
     class Meta:
-        nullable_fields = ('type',)
+        nullable_fields = ('type', 'description')
 
 
 class ConsoleServerPortTemplateForm(BootstrapMixin, forms.ModelForm):
@@ -1094,7 +1097,7 @@ class ConsoleServerPortTemplateForm(BootstrapMixin, forms.ModelForm):
     class Meta:
         model = ConsoleServerPortTemplate
         fields = [
-            'device_type', 'name', 'label', 'type',
+            'device_type', 'name', 'label', 'type', 'description',
         ]
         widgets = {
             'device_type': forms.HiddenInput(),
@@ -1118,9 +1121,12 @@ class ConsoleServerPortTemplateBulkEditForm(BootstrapMixin, BulkEditForm):
         required=False,
         widget=StaticSelect2()
     )
+    description = forms.CharField(
+        required=False
+    )
 
     class Meta:
-        nullable_fields = ('type',)
+        nullable_fields = ('type', 'description')
 
 
 class PowerPortTemplateForm(BootstrapMixin, forms.ModelForm):
@@ -1128,7 +1134,7 @@ class PowerPortTemplateForm(BootstrapMixin, forms.ModelForm):
     class Meta:
         model = PowerPortTemplate
         fields = [
-            'device_type', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw',
+            'device_type', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description',
         ]
         widgets = {
             'device_type': forms.HiddenInput(),
@@ -1172,9 +1178,12 @@ class PowerPortTemplateBulkEditForm(BootstrapMixin, BulkEditForm):
         required=False,
         help_text="Allocated power draw (watts)"
     )
+    description = forms.CharField(
+        required=False
+    )
 
     class Meta:
-        nullable_fields = ('type', 'maximum_draw', 'allocated_draw')
+        nullable_fields = ('type', 'maximum_draw', 'allocated_draw', 'description')
 
 
 class PowerOutletTemplateForm(BootstrapMixin, forms.ModelForm):
@@ -1182,7 +1191,7 @@ class PowerOutletTemplateForm(BootstrapMixin, forms.ModelForm):
     class Meta:
         model = PowerOutletTemplate
         fields = [
-            'device_type', 'name', 'label', 'type', 'power_port', 'feed_leg',
+            'device_type', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description',
         ]
         widgets = {
             'device_type': forms.HiddenInput(),
@@ -1251,9 +1260,12 @@ class PowerOutletTemplateBulkEditForm(BootstrapMixin, BulkEditForm):
         required=False,
         widget=StaticSelect2()
     )
+    description = forms.CharField(
+        required=False
+    )
 
     class Meta:
-        nullable_fields = ('type', 'power_port', 'feed_leg')
+        nullable_fields = ('type', 'power_port', 'feed_leg', 'description')
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
@@ -1272,7 +1284,7 @@ class InterfaceTemplateForm(BootstrapMixin, forms.ModelForm):
     class Meta:
         model = InterfaceTemplate
         fields = [
-            'device_type', 'name', 'label', 'type', 'mgmt_only',
+            'device_type', 'name', 'label', 'type', 'mgmt_only', 'description',
         ]
         widgets = {
             'device_type': forms.HiddenInput(),
@@ -1306,9 +1318,12 @@ class InterfaceTemplateBulkEditForm(BootstrapMixin, BulkEditForm):
         widget=BulkEditNullBooleanSelect,
         label='Management only'
     )
+    description = forms.CharField(
+        required=False
+    )
 
     class Meta:
-        nullable_fields = []
+        nullable_fields = ('description',)
 
 
 class FrontPortTemplateForm(BootstrapMixin, forms.ModelForm):
@@ -1316,7 +1331,7 @@ class FrontPortTemplateForm(BootstrapMixin, forms.ModelForm):
     class Meta:
         model = FrontPortTemplate
         fields = [
-            'device_type', 'name', 'type', 'rear_port', 'rear_port_position',
+            'device_type', 'name', 'type', 'rear_port', 'rear_port_position', 'description',
         ]
         widgets = {
             'device_type': forms.HiddenInput(),
@@ -1401,9 +1416,12 @@ class FrontPortTemplateBulkEditForm(BootstrapMixin, BulkEditForm):
         required=False,
         widget=StaticSelect2()
     )
+    description = forms.CharField(
+        required=False
+    )
 
     class Meta:
-        nullable_fields = ()
+        nullable_fields = ('description',)
 
 
 class RearPortTemplateForm(BootstrapMixin, forms.ModelForm):
@@ -1411,7 +1429,7 @@ class RearPortTemplateForm(BootstrapMixin, forms.ModelForm):
     class Meta:
         model = RearPortTemplate
         fields = [
-            'device_type', 'name', 'type', 'positions',
+            'device_type', 'name', 'type', 'positions', 'description',
         ]
         widgets = {
             'device_type': forms.HiddenInput(),
@@ -1442,9 +1460,12 @@ class RearPortTemplateBulkEditForm(BootstrapMixin, BulkEditForm):
         required=False,
         widget=StaticSelect2()
     )
+    description = forms.CharField(
+        required=False
+    )
 
     class Meta:
-        nullable_fields = ()
+        nullable_fields = ('description',)
 
 
 class DeviceBayTemplateForm(BootstrapMixin, forms.ModelForm):
@@ -1452,7 +1473,7 @@ class DeviceBayTemplateForm(BootstrapMixin, forms.ModelForm):
     class Meta:
         model = DeviceBayTemplate
         fields = [
-            'device_type', 'name', 'label',
+            'device_type', 'name', 'label', 'description',
         ]
         widgets = {
             'device_type': forms.HiddenInput(),
@@ -1460,7 +1481,9 @@ class DeviceBayTemplateForm(BootstrapMixin, forms.ModelForm):
 
 
 class DeviceBayTemplateCreateForm(ComponentTemplateCreateForm):
-    pass
+    description = forms.CharField(
+        required=False
+    )
 
 
 # TODO: DeviceBayTemplate has no fields suitable for bulk-editing yet

+ 53 - 0
netbox/dcim/migrations/0111_component_template_description.py

@@ -0,0 +1,53 @@
+# Generated by Django 3.0.6 on 2020-06-30 18:55
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('dcim', '0110_virtualchassis_name'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='consoleporttemplate',
+            name='description',
+            field=models.CharField(blank=True, max_length=200),
+        ),
+        migrations.AddField(
+            model_name='consoleserverporttemplate',
+            name='description',
+            field=models.CharField(blank=True, max_length=200),
+        ),
+        migrations.AddField(
+            model_name='devicebaytemplate',
+            name='description',
+            field=models.CharField(blank=True, max_length=200),
+        ),
+        migrations.AddField(
+            model_name='frontporttemplate',
+            name='description',
+            field=models.CharField(blank=True, max_length=200),
+        ),
+        migrations.AddField(
+            model_name='interfacetemplate',
+            name='description',
+            field=models.CharField(blank=True, max_length=200),
+        ),
+        migrations.AddField(
+            model_name='poweroutlettemplate',
+            name='description',
+            field=models.CharField(blank=True, max_length=200),
+        ),
+        migrations.AddField(
+            model_name='powerporttemplate',
+            name='description',
+            field=models.CharField(blank=True, max_length=200),
+        ),
+        migrations.AddField(
+            model_name='rearporttemplate',
+            name='description',
+            field=models.CharField(blank=True, max_length=200),
+        ),
+    ]

+ 5 - 0
netbox/dcim/models/device_component_templates.py

@@ -27,6 +27,11 @@ __all__ = (
 
 
 class ComponentTemplateModel(models.Model):
+    description = models.CharField(
+        max_length=200,
+        blank=True
+    )
+
     objects = RestrictedQuerySet.as_manager()
 
     class Meta:

+ 8 - 8
netbox/dcim/tables.py

@@ -486,7 +486,7 @@ class ConsolePortTemplateTable(ComponentTemplateTable):
 
     class Meta(BaseTable.Meta):
         model = ConsolePortTemplate
-        fields = ('pk', 'name', 'label', 'type', 'actions')
+        fields = ('pk', 'name', 'label', 'type', 'description', 'actions')
         empty_text = "None"
 
 
@@ -499,7 +499,7 @@ class ConsoleServerPortTemplateTable(ComponentTemplateTable):
 
     class Meta(BaseTable.Meta):
         model = ConsoleServerPortTemplate
-        fields = ('pk', 'name', 'label', 'type', 'actions')
+        fields = ('pk', 'name', 'label', 'type', 'description', 'actions')
         empty_text = "None"
 
 
@@ -512,7 +512,7 @@ class PowerPortTemplateTable(ComponentTemplateTable):
 
     class Meta(BaseTable.Meta):
         model = PowerPortTemplate
-        fields = ('pk', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'actions')
+        fields = ('pk', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description', 'actions')
         empty_text = "None"
 
 
@@ -525,7 +525,7 @@ class PowerOutletTemplateTable(ComponentTemplateTable):
 
     class Meta(BaseTable.Meta):
         model = PowerOutletTemplate
-        fields = ('pk', 'name', 'label', 'type', 'power_port', 'feed_leg', 'actions')
+        fields = ('pk', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description', 'actions')
         empty_text = "None"
 
 
@@ -541,7 +541,7 @@ class InterfaceTemplateTable(ComponentTemplateTable):
 
     class Meta(BaseTable.Meta):
         model = InterfaceTemplate
-        fields = ('pk', 'name', 'label', 'mgmt_only', 'type', 'actions')
+        fields = ('pk', 'name', 'label', 'mgmt_only', 'type', 'description', 'actions')
         empty_text = "None"
 
 
@@ -557,7 +557,7 @@ class FrontPortTemplateTable(ComponentTemplateTable):
 
     class Meta(BaseTable.Meta):
         model = FrontPortTemplate
-        fields = ('pk', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'actions')
+        fields = ('pk', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'actions')
         empty_text = "None"
 
 
@@ -570,7 +570,7 @@ class RearPortTemplateTable(ComponentTemplateTable):
 
     class Meta(BaseTable.Meta):
         model = RearPortTemplate
-        fields = ('pk', 'name', 'label', 'type', 'positions', 'actions')
+        fields = ('pk', 'name', 'label', 'type', 'positions', 'description', 'actions')
         empty_text = "None"
 
 
@@ -583,7 +583,7 @@ class DeviceBayTemplateTable(ComponentTemplateTable):
 
     class Meta(BaseTable.Meta):
         model = DeviceBayTemplate
-        fields = ('pk', 'name', 'label', 'actions')
+        fields = ('pk', 'name', 'label', 'description', 'actions')
         empty_text = "None"