From f7150645a14e2947122bc8e3715eecd3c105c3b2 Mon Sep 17 00:00:00 2001 From: Arthur Date: Thu, 17 Nov 2022 10:25:50 -0800 Subject: [PATCH] 8749 clone custom fields --- netbox/extras/api/serializers.py | 2 +- netbox/extras/forms/bulk_edit.py | 4 ++++ netbox/extras/forms/bulk_import.py | 2 +- netbox/extras/forms/model_forms.py | 2 +- .../0085_customfield_is_cloneable.py | 18 ++++++++++++++++++ netbox/extras/models/customfields.py | 7 ++++++- netbox/extras/tables/tables.py | 2 +- netbox/netbox/models/features.py | 9 +++++++++ netbox/templates/extras/customfield.html | 4 ++++ 9 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 netbox/extras/migrations/0085_customfield_is_cloneable.py diff --git a/netbox/extras/api/serializers.py b/netbox/extras/api/serializers.py index 740247df0..b952866a9 100644 --- a/netbox/extras/api/serializers.py +++ b/netbox/extras/api/serializers.py @@ -98,7 +98,7 @@ class CustomFieldSerializer(ValidatedModelSerializer): model = CustomField fields = [ 'id', 'url', 'display', 'content_types', 'type', 'object_type', 'data_type', 'name', 'label', 'group_name', - 'description', 'required', 'search_weight', 'filter_logic', 'ui_visibility', 'default', 'weight', + 'description', 'required', 'search_weight', '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 156e2e9b0..a4e0cabba 100644 --- a/netbox/extras/forms/bulk_edit.py +++ b/netbox/extras/forms/bulk_edit.py @@ -44,6 +44,10 @@ class CustomFieldBulkEditForm(BulkEditForm): required=False, initial='' ) + 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 15ed01ac4..28791ceb8 100644 --- a/netbox/extras/forms/bulk_import.py +++ b/netbox/extras/forms/bulk_import.py @@ -51,7 +51,7 @@ class CustomFieldImportForm(CSVModelForm): fields = ( 'name', 'label', 'group_name', 'type', 'content_types', 'object_type', 'required', 'description', 'search_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/model_forms.py b/netbox/extras/forms/model_forms.py index f4b491c85..af3e9187e 100644 --- a/netbox/extras/forms/model_forms.py +++ b/netbox/extras/forms/model_forms.py @@ -47,7 +47,7 @@ class CustomFieldForm(BootstrapMixin, forms.ModelForm): ('Custom Field', ( 'content_types', 'name', 'label', 'group_name', 'type', 'object_type', 'required', 'description', )), - ('Behavior', ('search_weight', 'filter_logic', 'ui_visibility', 'weight')), + ('Behavior', ('search_weight', 'filter_logic', 'ui_visibility', 'is_cloneable', 'weight')), ('Values', ('default', 'choices')), ('Validation', ('validation_minimum', 'validation_maximum', 'validation_regex')), ) diff --git a/netbox/extras/migrations/0085_customfield_is_cloneable.py b/netbox/extras/migrations/0085_customfield_is_cloneable.py new file mode 100644 index 000000000..79927f3e1 --- /dev/null +++ b/netbox/extras/migrations/0085_customfield_is_cloneable.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.2 on 2022-11-17 18:25 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('extras', '0084_staging'), + ] + + 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 f5ec3ce94..c178a6d04 100644 --- a/netbox/extras/models/customfields.py +++ b/netbox/extras/models/customfields.py @@ -163,13 +163,18 @@ class CustomField(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel): 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', 'search_weight', 'filter_logic', 'default', 'weight', 'validation_minimum', 'validation_maximum', 'validation_regex', 'choices', - 'ui_visibility', + 'ui_visibility', 'is_cloneable', ) class Meta: diff --git a/netbox/extras/tables/tables.py b/netbox/extras/tables/tables.py index 31b6f02c3..0f97d2a74 100644 --- a/netbox/extras/tables/tables.py +++ b/netbox/extras/tables/tables.py @@ -34,7 +34,7 @@ class CustomFieldTable(NetBoxTable): model = CustomField fields = ( 'pk', 'id', 'name', 'content_types', 'label', 'type', 'group_name', 'required', 'default', 'description', - 'search_weight', 'filter_logic', 'ui_visibility', 'weight', 'choices', 'created', 'last_updated', + 'search_weight', 'filter_logic', 'ui_visibility', 'is_cloneable', 'weight', 'choices', 'created', 'last_updated', ) default_columns = ('pk', 'name', 'content_types', 'label', 'group_name', 'type', 'required', 'description') diff --git a/netbox/netbox/models/features.py b/netbox/netbox/models/features.py index e82917a42..0283e5ede 100644 --- a/netbox/netbox/models/features.py +++ b/netbox/netbox/models/features.py @@ -121,6 +121,15 @@ class CloningMixin(models.Model): if is_taggable(self): attrs['tags'] = [tag.pk for tag in self.tags.all()] + # check custom fields + if hasattr(self, 'custom_field_data'): + from extras.models import CustomField + + for field in CustomField.objects.get_for_model(self): + if field.is_cloneable: + value = self.custom_field_data.get(field.name) + attrs[f'cf_{field.name}'] = field.deserialize(value) + return attrs diff --git a/netbox/templates/extras/customfield.html b/netbox/templates/extras/customfield.html index 4350bb738..4c103d4c6 100644 --- a/netbox/templates/extras/customfield.html +++ b/netbox/templates/extras/customfield.html @@ -60,6 +60,10 @@ UI Visibility {{ object.get_ui_visibility_display }} + + Cloneable + {% checkmark object.is_cloneable %} +