diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index f9dec9f69..3908b35af 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -16,9 +16,9 @@ from utilities.forms import ( from .models import ( DeviceBay, DeviceBayTemplate, CONNECTION_STATUS_CHOICES, CONNECTION_STATUS_PLANNED, CONNECTION_STATUS_CONNECTED, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceRole, DeviceType, - Interface, IFACE_FF_VIRTUAL, InterfaceConnection, InterfaceTemplate, Manufacturer, Module, Platform, PowerOutlet, - PowerOutletTemplate, PowerPort, PowerPortTemplate, RACK_TYPE_CHOICES, RACK_WIDTH_CHOICES, Rack, RackGroup, RackRole, - Site, STATUS_CHOICES, SUBDEVICE_ROLE_CHILD + Interface, IFACE_FF_CHOICES, IFACE_FF_VIRTUAL, InterfaceConnection, InterfaceTemplate, Manufacturer, Module, + Platform, PowerOutlet, PowerOutletTemplate, PowerPort, PowerPortTemplate, RACK_TYPE_CHOICES, RACK_WIDTH_CHOICES, + Rack, RackGroup, RackRole, Site, STATUS_CHOICES, SUBDEVICE_ROLE_CHILD ) @@ -1008,6 +1008,15 @@ class InterfaceBulkCreateForm(InterfaceCreateForm, BootstrapMixin): pk = forms.ModelMultipleChoiceField(queryset=Device.objects.all(), widget=forms.MultipleHiddenInput) +class InterfaceBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm): + pk = forms.ModelMultipleChoiceField(queryset=Interface.objects.all(), widget=forms.MultipleHiddenInput) + form_factor = forms.ChoiceField(choices=add_blank_choice(IFACE_FF_CHOICES), required=False) + description = forms.CharField(max_length=100, required=False) + + class Meta: + nullable_fields = ['description'] + + # # Interface connections # diff --git a/netbox/dcim/urls.py b/netbox/dcim/urls.py index dfeb06467..f5c5f69c0 100644 --- a/netbox/dcim/urls.py +++ b/netbox/dcim/urls.py @@ -3,10 +3,6 @@ from django.conf.urls import url from secrets.views import secret_add from . import views -from .models import ( - ConsolePortTemplate, ConsoleServerPortTemplate, DeviceBayTemplate, PowerPortTemplate, PowerOutletTemplate, - InterfaceTemplate, -) urlpatterns = [ @@ -159,6 +155,7 @@ urlpatterns = [ # Interfaces url(r'^devices/interfaces/add/$', views.InterfaceBulkAddView.as_view(), name='interface_add_multi'), url(r'^devices/(?P\d+)/interfaces/add/$', views.interface_add, name='interface_add'), + url(r'^devices/(?P\d+)/interfaces/edit/$', views.InterfaceBulkEditView.as_view(), name='interface_bulk_edit'), url(r'^devices/(?P\d+)/interfaces/delete/$', views.InterfaceBulkDeleteView.as_view(), name='interface_bulk_delete'), url(r'^devices/(?P\d+)/interface-connections/add/$', views.interfaceconnection_add, name='interfaceconnection_add'), url(r'^interface-connections/(?P\d+)/delete/$', views.interfaceconnection_delete, name='interfaceconnection_delete'), diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 44b39573c..112734c22 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -1425,6 +1425,14 @@ class InterfaceBulkAddView(PermissionRequiredMixin, BulkEditView): len(selected_devices))) +class InterfaceBulkEditView(PermissionRequiredMixin, BulkEditView): + permission_required = 'dcim.change_interface' + cls = Interface + parent_cls = Device + form = forms.InterfaceBulkEditForm + template_name = 'dcim/interface_bulk_edit.html' + + class InterfaceBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): permission_required = 'dcim.delete_interface' cls = Interface diff --git a/netbox/templates/dcim/device.html b/netbox/templates/dcim/device.html index 673c25c59..98f43be19 100644 --- a/netbox/templates/dcim/device.html +++ b/netbox/templates/dcim/device.html @@ -355,7 +355,7 @@ {% endif %} {% if interfaces or device.device_type.is_network_device %} {% if perms.dcim.delete_interface %} -
+ {% csrf_token %} {% endif %}
@@ -380,8 +380,13 @@ {% if perms.dcim.add_interface or perms.dcim.delete_interface %}