diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index ef3ff3873..0f697a276 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -1531,6 +1531,46 @@ class InterfaceBulkDisconnectForm(ConfirmationForm): pk = forms.ModelMultipleChoiceField(queryset=Interface.objects.all(), widget=forms.MultipleHiddenInput) +class InterfaceCSVForm(forms.ModelForm): + device = FlexibleModelChoiceField( + queryset=Device.objects.all(), + to_field_name='name', + help_text='Name or ID of device', + error_messages={'invalid_choice': 'Device not found.'} + ) + name = forms.CharField( + help_text='Name of interface' + ) + mac_address = forms.CharField( + required=False, + help_text='MAC address of interface' + ) + description = forms.CharField( + required=False, + help_text='Description for interface' + ) + + class Meta: + model = Interface + fields = [ + 'device', 'name', 'mac_address', 'description' + ] + + + def clean_interface(self): + + interface_name = self.cleaned_data.get('interface_name') + if not interface: + return None + + return interface + + +class InterfaceFilterForm(BootstrapMixin, forms.Form): + site = forms.ModelChoiceField(required=False, queryset=Site.objects.all(), to_field_name='slug') + device = forms.CharField(required=False, label='Device name') + + # # Interface connections # @@ -1696,41 +1736,6 @@ class InterfaceConnectionCSVForm(forms.ModelForm): return interface -class InterfaceCSVForm(forms.ModelForm): - device = FlexibleModelChoiceField( - queryset=Device.objects.all(), - to_field_name='name', - help_text='Name or ID of device', - error_messages={'invalid_choice': 'Device not found.'} - ) - name = forms.CharField( - help_text='Name of interface' - ) - mac_address = forms.CharField( - required=False, - help_text='MAC address of interface' - ) - description = forms.CharField( - required=False, - help_text='Description for interface' - ) - - class Meta: - model = Interface - fields = [ - 'device', 'name', 'mac_address', 'description' - ] - - - def clean_interface(self): - - interface_name = self.cleaned_data.get('interface_name') - if not interface: - return None - - return interface - - class InterfaceConnectionDeletionForm(ConfirmationForm): # Used for HTTP redirect upon successful deletion device = forms.ModelChoiceField(queryset=Device.objects.all(), widget=forms.HiddenInput(), required=False) diff --git a/netbox/dcim/urls.py b/netbox/dcim/urls.py index dbf85292b..f578728f0 100644 --- a/netbox/dcim/urls.py +++ b/netbox/dcim/urls.py @@ -177,7 +177,8 @@ urlpatterns = [ url(r'^interface-connections/(?P\d+)/delete/$', views.interfaceconnection_delete, name='interfaceconnection_delete'), url(r'^interfaces/(?P\d+)/edit/$', views.InterfaceEditView.as_view(), name='interface_edit'), url(r'^interfaces/(?P\d+)/delete/$', views.InterfaceDeleteView.as_view(), name='interface_delete'), - url(r'^interfaces/import/$', views.InterfacesBulkImportView.as_view(), name='interfaces_import'), + url(r'^interfaces/$', views.InterfaceListView.as_view(), name='interface_list'), + url(r'^interfaces/import/$', views.InterfacesBulkImportView.as_view(), name='interface_import'), # Device bays url(r'^devices/device-bays/add/$', views.DeviceBulkAddDeviceBayView.as_view(), name='device_bulk_add_devicebay'), diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 1f1586036..2a993c3b9 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -1548,6 +1548,22 @@ class InterfaceBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): table = tables.InterfaceTable +class InterfaceBulkImportView(PermissionRequiredMixin, BulkImportView): + permission_required = 'dcim.change_interface' + model_form = forms.InterfaceCSVForm + table = tables.InterfaceImportTable + default_return_url = 'dcim:interface_list' + + +class InterfaceListView(ObjectListView): + queryset = InterfaceConnection.objects.select_related('device')\ + .order_by('device', 'interface') + filter = filters.InterfaceFilter + filter_form = forms.InterfaceFilterForm + table = tables.InterfaceTable + template_name = 'dcim/interface_list.html' + + # # Device bays # @@ -1838,13 +1854,6 @@ class InterfaceConnectionsBulkImportView(PermissionRequiredMixin, BulkImportView default_return_url = 'dcim:interface_connections_list' -class InterfacesBulkImportView(PermissionRequiredMixin, BulkImportView): - permission_required = 'dcim.change_interface' - model_form = forms.InterfaceCSVForm - table = tables.InterfaceImportTable - default_return_url = 'dcim:device_list' - - # # Connections # diff --git a/netbox/templates/_base.html b/netbox/templates/_base.html index 134ffff4e..844d39295 100644 --- a/netbox/templates/_base.html +++ b/netbox/templates/_base.html @@ -86,7 +86,7 @@
  • Import Devices
  • {% endif %} {% if perms.dcim.add_interface %} -
  • Import Interfaces
  • +
  • Import Interfaces
  • {% endif %} {% if perms.ipam.add_device or perms.ipam.add_devicetype %}
  • diff --git a/netbox/templates/dcim/device.html b/netbox/templates/dcim/device.html index ce18148c5..3e055333c 100644 --- a/netbox/templates/dcim/device.html +++ b/netbox/templates/dcim/device.html @@ -376,7 +376,7 @@
    {% if perms.dcim.add_interface %} - + Import Interfaces diff --git a/netbox/templates/dcim/interface_list.html b/netbox/templates/dcim/interface_list.html new file mode 100644 index 000000000..7e2def732 --- /dev/null +++ b/netbox/templates/dcim/interface_list.html @@ -0,0 +1,24 @@ +{% extends '_base.html' %} + +{% block title %}Interfaces{% endblock %} + +{% block content %} +
    + {% if perms.dcim.add_interfaces %} + + + Import Interfaces + + {% endif %} + {% include 'inc/export_button.html' with obj_type='interface' %} +
    +

    Interface Connections

    +
    +
    + {% include 'responsive_table.html' %} +
    +
    + {% include 'inc/search_panel.html' %} +
    +
    +{% endblock %}