From 052555c3f7bc826eeb24e0f32f5dbea6aa903b91 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 24 Jun 2020 10:02:40 -0400 Subject: [PATCH] Add bulk renaming function for VM interfaces --- netbox/dcim/forms.py | 28 +-------- netbox/dcim/views.py | 58 +------------------ .../obj_bulk_rename.html} | 0 .../virtualization/virtualmachine.html | 3 + netbox/utilities/forms.py | 24 ++++++++ netbox/utilities/views.py | 53 +++++++++++++++++ netbox/virtualization/forms.py | 13 ++++- netbox/virtualization/urls.py | 1 + netbox/virtualization/views.py | 9 ++- 9 files changed, 103 insertions(+), 86 deletions(-) rename netbox/templates/{dcim/bulk_rename.html => utilities/obj_bulk_rename.html} (100%) diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index 4d8fc9d81..099676181 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -23,12 +23,12 @@ from tenancy.forms import TenancyFilterForm, TenancyForm from tenancy.models import Tenant, TenantGroup from utilities.forms import ( APISelect, APISelectMultiple, add_blank_choice, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, - ColorSelect, CommentField, ConfirmationForm, CSVChoiceField, CSVModelChoiceField, CSVModelForm, + BulkRenameForm, ColorSelect, CommentField, ConfirmationForm, CSVChoiceField, CSVModelChoiceField, CSVModelForm, DynamicModelChoiceField, DynamicModelMultipleChoiceField, ExpandableNameField, form_from_model, JSONField, NumericArrayField, SelectWithPK, SmallTextarea, SlugField, StaticSelect2, StaticSelect2Multiple, TagFilterField, BOOLEAN_WITH_BLANK_CHOICES, ) -from virtualization.models import Cluster, ClusterGroup, VirtualMachine +from virtualization.models import Cluster, ClusterGroup from .choices import * from .constants import * from .models import ( @@ -150,30 +150,6 @@ class LabeledComponentForm(BootstrapMixin, forms.Form): }, code='label_pattern_mismatch') -class BulkRenameForm(forms.Form): - """ - An extendable form to be used for renaming device components in bulk. - """ - find = forms.CharField() - replace = forms.CharField() - use_regex = forms.BooleanField( - required=False, - initial=True, - label='Use regular expressions' - ) - - def clean(self): - - # Validate regular expression in "find" field - if self.cleaned_data['use_regex']: - try: - re.compile(self.cleaned_data['find']) - except re.error: - raise forms.ValidationError({ - 'find': "Invalid regular expression" - }) - - # # Fields # diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 6aad18bd3..ba32a7643 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -1,5 +1,4 @@ from collections import OrderedDict -import re from django.conf import settings from django.contrib import messages @@ -25,8 +24,9 @@ from utilities.paginator import EnhancedPaginator from utilities.permissions import get_permission_for_model from utilities.utils import csv_format from utilities.views import ( - BulkComponentCreateView, BulkDeleteView, BulkEditView, BulkImportView, ComponentCreateView, GetReturnURLMixin, - ObjectView, ObjectImportView, ObjectDeleteView, ObjectEditView, ObjectListView, ObjectPermissionRequiredMixin, + BulkComponentCreateView, BulkDeleteView, BulkEditView, BulkImportView, BulkRenameView, ComponentCreateView, + GetReturnURLMixin, ObjectView, ObjectImportView, ObjectDeleteView, ObjectEditView, ObjectListView, + ObjectPermissionRequiredMixin, ) from virtualization.models import VirtualMachine from . import filters, forms, tables @@ -41,58 +41,6 @@ from .models import ( ) -class BulkRenameView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): - """ - An extendable view for renaming device components in bulk. - """ - queryset = None - form = None - template_name = 'dcim/bulk_rename.html' - - def get_required_permission(self): - return get_permission_for_model(self.queryset.model, 'change') - - def post(self, request): - - if '_preview' in request.POST or '_apply' in request.POST: - form = self.form(request.POST, initial={'pk': request.POST.getlist('pk')}) - selected_objects = self.queryset.filter(pk__in=form.initial['pk']) - - if form.is_valid(): - for obj in selected_objects: - find = form.cleaned_data['find'] - replace = form.cleaned_data['replace'] - if form.cleaned_data['use_regex']: - try: - obj.new_name = re.sub(find, replace, obj.name) - # Catch regex group reference errors - except re.error: - obj.new_name = obj.name - else: - obj.new_name = obj.name.replace(find, replace) - - if '_apply' in request.POST: - for obj in selected_objects: - obj.name = obj.new_name - obj.save() - messages.success(request, "Renamed {} {}".format( - len(selected_objects), - self.queryset.model._meta.verbose_name_plural - )) - return redirect(self.get_return_url(request)) - - else: - form = self.form(initial={'pk': request.POST.getlist('pk')}) - selected_objects = self.queryset.filter(pk__in=form.initial['pk']) - - return render(request, self.template_name, { - 'form': form, - 'obj_type_plural': self.queryset.model._meta.verbose_name_plural, - 'selected_objects': selected_objects, - 'return_url': self.get_return_url(request), - }) - - class BulkDisconnectView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): """ An extendable view for disconnection console/power/interface components in bulk. diff --git a/netbox/templates/dcim/bulk_rename.html b/netbox/templates/utilities/obj_bulk_rename.html similarity index 100% rename from netbox/templates/dcim/bulk_rename.html rename to netbox/templates/utilities/obj_bulk_rename.html diff --git a/netbox/templates/virtualization/virtualmachine.html b/netbox/templates/virtualization/virtualmachine.html index 0f2523af7..9cc206dac 100644 --- a/netbox/templates/virtualization/virtualmachine.html +++ b/netbox/templates/virtualization/virtualmachine.html @@ -292,6 +292,9 @@ {% if perms.virtualization.add_vminterface or perms.virtualization.delete_vminterface %}