diff --git a/netbox/extras/api/serializers.py b/netbox/extras/api/serializers.py index 764c7750a..02b63a567 100644 --- a/netbox/extras/api/serializers.py +++ b/netbox/extras/api/serializers.py @@ -91,7 +91,7 @@ class CustomFieldSerializer(ValidatedModelSerializer): model = CustomField fields = [ 'id', 'url', 'display', 'content_types', 'type', 'object_type', 'data_type', 'name', 'label', 'group_name', - 'description', 'required', 'filter_logic', 'ui_visibility', 'default', 'weight', 'validation_minimum', + 'description', 'required', 'filter_logic', 'ui_visibility', 'is_cloneable', 'default', 'weight', 'validation_minimum', 'validation_maximum', 'validation_regex', 'choices', 'created', 'last_updated', ] diff --git a/netbox/extras/forms/bulk_edit.py b/netbox/extras/forms/bulk_edit.py index b1d8a6c21..a0ee8bd64 100644 --- a/netbox/extras/forms/bulk_edit.py +++ b/netbox/extras/forms/bulk_edit.py @@ -44,6 +44,10 @@ class CustomFieldBulkEditForm(BulkEditForm): initial='', widget=StaticSelect() ) + is_cloneable = forms.NullBooleanField( + required=False, + widget=BulkEditNullBooleanSelect() + ) nullable_fields = ('group_name', 'description',) diff --git a/netbox/extras/forms/bulk_import.py b/netbox/extras/forms/bulk_import.py index e83cac3b9..5aab804cb 100644 --- a/netbox/extras/forms/bulk_import.py +++ b/netbox/extras/forms/bulk_import.py @@ -48,7 +48,7 @@ class CustomFieldCSVForm(CSVModelForm): fields = ( 'name', 'label', 'group_name', 'type', 'content_types', 'object_type', 'required', 'description', 'weight', 'filter_logic', 'default', 'choices', 'weight', 'validation_minimum', 'validation_maximum', - 'validation_regex', 'ui_visibility', + 'validation_regex', 'ui_visibility', 'is_cloneable', ) diff --git a/netbox/extras/forms/models.py b/netbox/extras/forms/models.py index bea1fbcc1..c86e3b5bc 100644 --- a/netbox/extras/forms/models.py +++ b/netbox/extras/forms/models.py @@ -43,7 +43,7 @@ class CustomFieldForm(BootstrapMixin, forms.ModelForm): ('Custom Field', ( 'content_types', 'name', 'label', 'group_name', 'type', 'object_type', 'weight', 'required', 'description', )), - ('Behavior', ('filter_logic', 'ui_visibility')), + ('Behavior', ('filter_logic', 'ui_visibility', 'is_cloneable')), ('Values', ('default', 'choices')), ('Validation', ('validation_minimum', 'validation_maximum', 'validation_regex')), ) diff --git a/netbox/extras/migrations/0078_customfield_is_cloneable.py b/netbox/extras/migrations/0078_customfield_is_cloneable.py new file mode 100644 index 000000000..356b86ce1 --- /dev/null +++ b/netbox/extras/migrations/0078_customfield_is_cloneable.py @@ -0,0 +1,18 @@ +# Generated by Django 4.0.8 on 2022-11-15 18:59 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('extras', '0077_customlink_extend_text_and_url'), + ] + + operations = [ + migrations.AddField( + model_name='customfield', + name='is_cloneable', + field=models.BooleanField(default=False), + ), + ] diff --git a/netbox/extras/models/customfields.py b/netbox/extras/models/customfields.py index d52d73848..6397fb62c 100644 --- a/netbox/extras/models/customfields.py +++ b/netbox/extras/models/customfields.py @@ -143,12 +143,17 @@ class CustomField(CloningMixin, ExportTemplatesMixin, WebhooksMixin, ChangeLogge verbose_name='UI visibility', help_text='Specifies the visibility of custom field in the UI' ) + is_cloneable = models.BooleanField( + default=False, + verbose_name='Cloneable', + help_text='If true, this field will be copied over when cloning objects.' + ) objects = CustomFieldManager() clone_fields = ( 'content_types', 'type', 'object_type', 'group_name', 'description', 'required', 'filter_logic', 'default', - 'weight', 'validation_minimum', 'validation_maximum', 'validation_regex', 'choices', 'ui_visibility', + 'weight', 'validation_minimum', 'validation_maximum', 'validation_regex', 'choices', 'ui_visibility', 'is_cloneable', ) class Meta: diff --git a/netbox/extras/tables/tables.py b/netbox/extras/tables/tables.py index 1df5c9487..e029c57bc 100644 --- a/netbox/extras/tables/tables.py +++ b/netbox/extras/tables/tables.py @@ -29,12 +29,13 @@ class CustomFieldTable(NetBoxTable): content_types = columns.ContentTypesColumn() required = columns.BooleanColumn() ui_visibility = columns.ChoiceFieldColumn(verbose_name="UI visibility") + is_cloneable = columns.BooleanColumn() class Meta(NetBoxTable.Meta): model = CustomField fields = ( 'pk', 'id', 'name', 'content_types', 'label', 'type', 'group_name', 'required', 'weight', 'default', - 'description', 'filter_logic', 'ui_visibility', 'choices', 'created', 'last_updated', + 'description', 'filter_logic', 'ui_visibility', 'is_cloneable', 'choices', 'created', 'last_updated', ) default_columns = ('pk', 'name', 'content_types', 'label', 'group_name', 'type', 'required', 'description') diff --git a/netbox/templates/extras/customfield.html b/netbox/templates/extras/customfield.html index ff4e6e08c..c74dda114 100644 --- a/netbox/templates/extras/customfield.html +++ b/netbox/templates/extras/customfield.html @@ -50,6 +50,10 @@ UI Visibility {{ object.get_ui_visibility_display }} + + Cloneable + {% checkmark object.is_cloneable %} +