Browse Source

Closes #838: Display details of all objects being edited/deleted in bulk

Jeremy Stretch 8 years ago
parent
commit
dd1991f2c6

+ 5 - 2
netbox/circuits/views.py

@@ -78,8 +78,8 @@ class ProviderBulkEditView(PermissionRequiredMixin, BulkEditView):
     permission_required = 'circuits.change_provider'
     cls = Provider
     filter = filters.ProviderFilter
+    table = tables.ProviderTable
     form = forms.ProviderBulkEditForm
-    template_name = 'circuits/provider_bulk_edit.html'
     default_return_url = 'circuits:provider_list'
 
 
@@ -87,6 +87,7 @@ class ProviderBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
     permission_required = 'circuits.delete_provider'
     cls = Provider
     filter = filters.ProviderFilter
+    table = tables.ProviderTable
     default_return_url = 'circuits:provider_list'
 
 
@@ -116,6 +117,7 @@ class CircuitTypeEditView(CircuitTypeCreateView):
 class CircuitTypeBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
     permission_required = 'circuits.delete_circuittype'
     cls = CircuitType
+    table = tables.CircuitTypeTable
     default_return_url = 'circuits:circuittype_list'
 
 
@@ -183,8 +185,8 @@ class CircuitBulkEditView(PermissionRequiredMixin, BulkEditView):
     permission_required = 'circuits.change_circuit'
     cls = Circuit
     filter = filters.CircuitFilter
+    table = tables.CircuitTable
     form = forms.CircuitBulkEditForm
-    template_name = 'circuits/circuit_bulk_edit.html'
     default_return_url = 'circuits:circuit_list'
 
 
@@ -192,6 +194,7 @@ class CircuitBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
     permission_required = 'circuits.delete_circuit'
     cls = Circuit
     filter = filters.CircuitFilter
+    table = tables.CircuitTable
     default_return_url = 'circuits:circuit_list'
 
 

+ 49 - 3
netbox/dcim/tables.py

@@ -5,9 +5,9 @@ from django_tables2.utils import Accessor
 
 from utilities.tables import BaseTable, ToggleColumn
 from .models import (
-    ConsolePort, ConsolePortTemplate, ConsoleServerPortTemplate, Device, DeviceBayTemplate, DeviceRole, DeviceType,
-    Interface, InterfaceTemplate, Manufacturer, Platform, PowerOutletTemplate, PowerPort, PowerPortTemplate, Rack,
-    RackGroup, RackReservation, Region, Site,
+    ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay,
+    DeviceBayTemplate, DeviceRole, DeviceType, Interface, InterfaceTemplate, Manufacturer, Platform, PowerOutlet,
+    PowerOutletTemplate, PowerPort, PowerPortTemplate, Rack, RackGroup, RackReservation, Region, Site,
 )
 
 
@@ -454,6 +454,52 @@ class DeviceImportTable(BaseTable):
 
 
 #
+# Device components
+#
+
+class ConsolePortTable(BaseTable):
+
+    class Meta(BaseTable.Meta):
+        model = ConsolePort
+        fields = ('name',)
+
+
+class ConsoleServerPortTable(BaseTable):
+
+    class Meta(BaseTable.Meta):
+        model = ConsoleServerPort
+        fields = ('name',)
+
+
+class PowerPortTable(BaseTable):
+
+    class Meta(BaseTable.Meta):
+        model = PowerPort
+        fields = ('name',)
+
+
+class PowerOutletTable(BaseTable):
+
+    class Meta(BaseTable.Meta):
+        model = PowerOutlet
+        fields = ('name',)
+
+
+class InterfaceTable(BaseTable):
+
+    class Meta(BaseTable.Meta):
+        model = Interface
+        fields = ('name', 'form_factor', 'lag', 'enabled', 'mgmt_only', 'description')
+
+
+class DeviceBayTable(BaseTable):
+
+    class Meta(BaseTable.Meta):
+        model = DeviceBay
+        fields = ('name',)
+
+
+#
 # Device connections
 #
 

+ 28 - 6
netbox/dcim/views.py

@@ -205,6 +205,7 @@ class RegionEditView(RegionCreateView):
 class RegionBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
     permission_required = 'dcim.delete_region'
     cls = Region
+    table = tables.RegionTable
     default_return_url = 'dcim:region_list'
 
 
@@ -274,8 +275,8 @@ class SiteBulkEditView(PermissionRequiredMixin, BulkEditView):
     permission_required = 'dcim.change_site'
     cls = Site
     filter = filters.SiteFilter
+    table = tables.SiteTable
     form = forms.SiteBulkEditForm
-    template_name = 'dcim/site_bulk_edit.html'
     default_return_url = 'dcim:site_list'
 
 
@@ -308,6 +309,7 @@ class RackGroupBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
     permission_required = 'dcim.delete_rackgroup'
     cls = RackGroup
     filter = filters.RackGroupFilter
+    table = tables.RackGroupTable
     default_return_url = 'dcim:rackgroup_list'
 
 
@@ -337,6 +339,7 @@ class RackRoleEditView(RackRoleCreateView):
 class RackRoleBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
     permission_required = 'dcim.delete_rackrole'
     cls = RackRole
+    table = tables.RackRoleTable
     default_return_url = 'dcim:rackrole_list'
 
 
@@ -456,8 +459,8 @@ class RackBulkEditView(PermissionRequiredMixin, BulkEditView):
     permission_required = 'dcim.change_rack'
     cls = Rack
     filter = filters.RackFilter
+    table = tables.RackTable
     form = forms.RackBulkEditForm
-    template_name = 'dcim/rack_bulk_edit.html'
     default_return_url = 'dcim:rack_list'
 
 
@@ -465,6 +468,7 @@ class RackBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
     permission_required = 'dcim.delete_rack'
     cls = Rack
     filter = filters.RackFilter
+    table = tables.RackTable
     default_return_url = 'dcim:rack_list'
 
 
@@ -510,6 +514,7 @@ class RackReservationDeleteView(PermissionRequiredMixin, ObjectDeleteView):
 class RackReservationBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
     permission_required = 'dcim.delete_rackreservation'
     cls = RackReservation
+    table = tables.RackReservationTable
     default_return_url = 'dcim:rackreservation_list'
 
 
@@ -539,6 +544,7 @@ class ManufacturerEditView(ManufacturerCreateView):
 class ManufacturerBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
     permission_required = 'dcim.delete_manufacturer'
     cls = Manufacturer
+    table = tables.ManufacturerTable
     default_return_url = 'dcim:manufacturer_list'
 
 
@@ -622,8 +628,8 @@ class DeviceTypeBulkEditView(PermissionRequiredMixin, BulkEditView):
     permission_required = 'dcim.change_devicetype'
     cls = DeviceType
     filter = filters.DeviceTypeFilter
+    table = tables.DeviceTypeTable
     form = forms.DeviceTypeBulkEditForm
-    template_name = 'dcim/devicetype_bulk_edit.html'
     default_return_url = 'dcim:devicetype_list'
 
 
@@ -631,6 +637,7 @@ class DeviceTypeBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
     permission_required = 'dcim.delete_devicetype'
     cls = DeviceType
     filter = filters.DeviceTypeFilter
+    table = tables.DeviceTypeTable
     default_return_url = 'dcim:devicetype_list'
 
 
@@ -653,6 +660,7 @@ class ConsolePortTemplateBulkDeleteView(PermissionRequiredMixin, BulkDeleteView)
     parent_field = 'device_type'
     cls = ConsolePortTemplate
     parent_cls = DeviceType
+    table = tables.ConsolePortTemplateTable
 
 
 class ConsoleServerPortTemplateCreateView(PermissionRequiredMixin, ComponentCreateView):
@@ -668,6 +676,7 @@ class ConsoleServerPortTemplateBulkDeleteView(PermissionRequiredMixin, BulkDelet
     permission_required = 'dcim.delete_consoleserverporttemplate'
     cls = ConsoleServerPortTemplate
     parent_cls = DeviceType
+    table = tables.ConsoleServerPortTemplateTable
 
 
 class PowerPortTemplateCreateView(PermissionRequiredMixin, ComponentCreateView):
@@ -683,6 +692,7 @@ class PowerPortTemplateBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
     permission_required = 'dcim.delete_powerporttemplate'
     cls = PowerPortTemplate
     parent_cls = DeviceType
+    table = tables.PowerPortTemplateTable
 
 
 class PowerOutletTemplateCreateView(PermissionRequiredMixin, ComponentCreateView):
@@ -698,6 +708,7 @@ class PowerOutletTemplateBulkDeleteView(PermissionRequiredMixin, BulkDeleteView)
     permission_required = 'dcim.delete_poweroutlettemplate'
     cls = PowerOutletTemplate
     parent_cls = DeviceType
+    table = tables.PowerOutletTemplateTable
 
 
 class InterfaceTemplateCreateView(PermissionRequiredMixin, ComponentCreateView):
@@ -713,14 +724,15 @@ class InterfaceTemplateBulkEditView(PermissionRequiredMixin, BulkEditView):
     permission_required = 'dcim.change_interfacetemplate'
     cls = InterfaceTemplate
     parent_cls = DeviceType
+    table = tables.InterfaceTemplateTable
     form = forms.InterfaceTemplateBulkEditForm
-    template_name = 'dcim/interfacetemplate_bulk_edit.html'
 
 
 class InterfaceTemplateBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
     permission_required = 'dcim.delete_interfacetemplate'
     cls = InterfaceTemplate
     parent_cls = DeviceType
+    table = tables.InterfaceTemplateTable
 
 
 class DeviceBayTemplateCreateView(PermissionRequiredMixin, ComponentCreateView):
@@ -736,6 +748,7 @@ class DeviceBayTemplateBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
     permission_required = 'dcim.delete_devicebaytemplate'
     cls = DeviceBayTemplate
     parent_cls = DeviceType
+    table = tables.DeviceBayTemplateTable
 
 
 #
@@ -764,6 +777,7 @@ class DeviceRoleEditView(DeviceRoleCreateView):
 class DeviceRoleBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
     permission_required = 'dcim.delete_devicerole'
     cls = DeviceRole
+    table = tables.DeviceRoleTable
     default_return_url = 'dcim:devicerole_list'
 
 
@@ -793,6 +807,7 @@ class PlatformEditView(PlatformCreateView):
 class PlatformBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
     permission_required = 'dcim.delete_platform'
     cls = Platform
+    table = tables.PlatformTable
     default_return_url = 'dcim:platform_list'
 
 
@@ -957,8 +972,8 @@ class DeviceBulkEditView(PermissionRequiredMixin, BulkEditView):
     permission_required = 'dcim.change_device'
     cls = Device
     filter = filters.DeviceFilter
+    table = tables.DeviceTable
     form = forms.DeviceBulkEditForm
-    template_name = 'dcim/device_bulk_edit.html'
     default_return_url = 'dcim:device_list'
 
 
@@ -966,6 +981,7 @@ class DeviceBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
     permission_required = 'dcim.delete_device'
     cls = Device
     filter = filters.DeviceFilter
+    table = tables.DeviceTable
     default_return_url = 'dcim:device_list'
 
 
@@ -1073,6 +1089,7 @@ class ConsolePortBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
     permission_required = 'dcim.delete_consoleport'
     cls = ConsolePort
     parent_cls = Device
+    table = tables.ConsolePortTable
 
 
 class ConsoleConnectionsBulkImportView(PermissionRequiredMixin, BulkImportView):
@@ -1198,6 +1215,7 @@ class ConsoleServerPortBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
     permission_required = 'dcim.delete_consoleserverport'
     cls = ConsoleServerPort
     parent_cls = Device
+    table = tables.ConsoleServerPortTable
 
 
 #
@@ -1304,6 +1322,7 @@ class PowerPortBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
     permission_required = 'dcim.delete_powerport'
     cls = PowerPort
     parent_cls = Device
+    table = tables.PowerPortTable
 
 
 class PowerConnectionsBulkImportView(PermissionRequiredMixin, BulkImportView):
@@ -1431,6 +1450,7 @@ class PowerOutletBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
     permission_required = 'dcim.delete_poweroutlet'
     cls = PowerOutlet
     parent_cls = Device
+    table = tables.PowerOutletTable
 
 
 #
@@ -1473,14 +1493,15 @@ class InterfaceBulkEditView(PermissionRequiredMixin, BulkEditView):
     permission_required = 'dcim.change_interface'
     cls = Interface
     parent_cls = Device
+    table = tables.InterfaceTable
     form = forms.InterfaceBulkEditForm
-    template_name = 'dcim/interface_bulk_edit.html'
 
 
 class InterfaceBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
     permission_required = 'dcim.delete_interface'
     cls = Interface
     parent_cls = Device
+    table = tables.InterfaceTable
 
 
 #
@@ -1561,6 +1582,7 @@ class DeviceBayBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
     permission_required = 'dcim.delete_devicebay'
     cls = DeviceBay
     parent_cls = Device
+    table = tables.DeviceBayTable
 
 
 #

+ 5 - 5
netbox/ipam/views.py

@@ -143,8 +143,8 @@ class VRFBulkEditView(PermissionRequiredMixin, BulkEditView):
     permission_required = 'ipam.change_vrf'
     cls = VRF
     filter = filters.VRFFilter
+    table = tables.VRFTable
     form = forms.VRFBulkEditForm
-    template_name = 'ipam/vrf_bulk_edit.html'
     default_return_url = 'ipam:vrf_list'
 
 
@@ -361,8 +361,8 @@ class AggregateBulkEditView(PermissionRequiredMixin, BulkEditView):
     permission_required = 'ipam.change_aggregate'
     cls = Aggregate
     filter = filters.AggregateFilter
+    table = tables.AggregateTable
     form = forms.AggregateBulkEditForm
-    template_name = 'ipam/aggregate_bulk_edit.html'
     default_return_url = 'ipam:aggregate_list'
 
 
@@ -565,8 +565,8 @@ class PrefixBulkEditView(PermissionRequiredMixin, BulkEditView):
     permission_required = 'ipam.change_prefix'
     cls = Prefix
     filter = filters.PrefixFilter
+    table = tables.PrefixTable
     form = forms.PrefixBulkEditForm
-    template_name = 'ipam/prefix_bulk_edit.html'
     default_return_url = 'ipam:prefix_list'
 
 
@@ -670,8 +670,8 @@ class IPAddressBulkEditView(PermissionRequiredMixin, BulkEditView):
     permission_required = 'ipam.change_ipaddress'
     cls = IPAddress
     filter = filters.IPAddressFilter
+    table = tables.IPAddressTable
     form = forms.IPAddressBulkEditForm
-    template_name = 'ipam/ipaddress_bulk_edit.html'
     default_return_url = 'ipam:ipaddress_list'
 
 
@@ -772,8 +772,8 @@ class VLANBulkEditView(PermissionRequiredMixin, BulkEditView):
     permission_required = 'ipam.change_vlan'
     cls = VLAN
     filter = filters.VLANFilter
+    table = tables.VLANTable
     form = forms.VLANBulkEditForm
-    template_name = 'ipam/vlan_bulk_edit.html'
     default_return_url = 'ipam:vlan_list'
 
 

+ 1 - 2
netbox/secrets/views.py

@@ -4,7 +4,6 @@ import base64
 from django.contrib import messages
 from django.contrib.auth.decorators import permission_required, login_required
 from django.contrib.auth.mixins import PermissionRequiredMixin
-from django.db import transaction, IntegrityError
 from django.db.models import Count
 from django.shortcuts import get_object_or_404, redirect, render
 from django.urls import reverse
@@ -241,8 +240,8 @@ class SecretBulkEditView(PermissionRequiredMixin, BulkEditView):
     permission_required = 'secrets.change_secret'
     cls = Secret
     filter = filters.SecretFilter
+    table = tables.SecretTable
     form = forms.SecretBulkEditForm
-    template_name = 'secrets/secret_bulk_edit.html'
     default_return_url = 'secrets:secret_list'
 
 

+ 0 - 23
netbox/templates/circuits/circuit_bulk_edit.html

@@ -1,23 +0,0 @@
-{% extends 'utilities/bulk_edit_form.html' %}
-{% load form_helpers %}
-
-{% block title %}Circuit Bulk Edit{% endblock %}
-
-{% block selected_objects_table %}
-    <tr>
-        <th>Circuit</th>
-        <th>Type</th>
-        <th>Provider</th>
-        <th>Port speed</th>
-        <th>Commit rate</th>
-    </tr>
-    {% for circuit in selected_objects %}
-        <tr>
-            <td><a href="{% url 'circuits:circuit' pk=circuit.pk %}">{{ circuit }}</a></td>
-            <td>{{ circuit.type }}</td>
-            <td>{{ circuit.provider }}</td>
-            <td>{{ circuit.port_speed_human }}</td>
-            <td>{{ circuit.commit_rate_human }}</td>
-        </tr>
-    {% endfor %}
-{% endblock %}

+ 0 - 19
netbox/templates/circuits/provider_bulk_edit.html

@@ -1,19 +0,0 @@
-{% extends 'utilities/bulk_edit_form.html' %}
-{% load form_helpers %}
-
-{% block title %}Provider Bulk Edit{% endblock %}
-
-{% block selected_objects_table %}
-    <tr>
-        <th>Provider</th>
-        <th>Account</th>
-        <th>ASN</th>
-    </tr>
-    {% for provider in selected_objects %}
-        <tr>
-            <td><a href="{% url 'circuits:provider' slug=provider.slug %}">{{ provider }}</a></td>
-            <td>{{ provider.account }}</td>
-            <td>{{ provider.asn }}</td>
-        </tr>
-    {% endfor %}
-{% endblock %}

+ 0 - 23
netbox/templates/dcim/device_bulk_edit.html

@@ -1,23 +0,0 @@
-{% extends 'utilities/bulk_edit_form.html' %}
-{% load form_helpers %}
-
-{% block title %}Device Bulk Edit{% endblock %}
-
-{% block selected_objects_table %}
-    <tr>
-        <th>Device</th>
-        <th>Type</th>
-        <th>Role</th>
-        <th>Tenant</th>
-        <th>Serial</th>
-    </tr>
-    {% for device in selected_objects %}
-        <tr>
-            <td><a href="{% url 'dcim:device' pk=device.pk %}">{{ device }}</a></td>
-            <td>{{ device.device_type.full_name }}</td>
-            <td>{{ device.device_role }}</td>
-            <td>{{ device.tenant }}</td>
-            <td>{{ device.serial }}</td>
-        </tr>
-    {% endfor %}
-{% endblock %}

+ 0 - 19
netbox/templates/dcim/devicetype_bulk_edit.html

@@ -1,19 +0,0 @@
-{% extends 'utilities/bulk_edit_form.html' %}
-{% load form_helpers %}
-
-{% block title %}Device Type Bulk Edit{% endblock %}
-
-{% block selected_objects_table %}
-    <tr>
-        <th>Device type</th>
-        <th>Manufacturer</th>
-        <th>Height</th>
-    </tr>
-    {% for devicetype in selected_objects %}
-        <tr>
-            <td><a href="{% url 'dcim:devicetype' pk=devicetype.pk %}">{{ devicetype.model }}</a></td>
-            <td>{{ devicetype.manufacturer }}</td>
-            <td>{{ devicetype.u_height }}U</td>
-        </tr>
-    {% endfor %}
-{% endblock %}

+ 0 - 17
netbox/templates/dcim/interface_bulk_edit.html

@@ -1,17 +0,0 @@
-{% extends 'utilities/bulk_edit_form.html' %}
-{% load form_helpers %}
-
-{% block title %}Interface Bulk Edit{% endblock %}
-
-{% block selected_objects_table %}
-    <tr>
-        <th>Name</th>
-        <th>Form Factor</th>
-    </tr>
-    {% for iface in selected_objects %}
-        <tr>
-            <td>{{ iface.name }}</td>
-            <td>{{ iface.get_form_factor_display }}</td>
-        </tr>
-    {% endfor %}
-{% endblock %}

+ 0 - 25
netbox/templates/dcim/interfacetemplate_bulk_edit.html

@@ -1,25 +0,0 @@
-{% extends 'utilities/bulk_edit_form.html' %}
-{% load form_helpers %}
-
-{% block title %}Interface Template Bulk Edit{% endblock %}
-
-{% block selected_objects_table %}
-    <tr>
-        <th>Name</th>
-        <th>Form Factor</th>
-        <th>Management</th>
-    </tr>
-    {% for iface in selected_objects %}
-        <tr>
-            <td>{{ iface.name }}</td>
-            <td>{{ iface.get_form_factor_display }}</td>
-            <td>
-                {% if iface.mgmt_only %}
-                    <i class="glyphicon glyphicon-ok text-success" title="Yes"></i>
-                {% else %}
-                    <i class="glyphicon glyphicon-remove text-danger" title="No"></i>
-                {% endif %}
-            </td>
-        </tr>
-    {% endfor %}
-{% endblock %}

+ 0 - 29
netbox/templates/dcim/rack_bulk_edit.html

@@ -1,29 +0,0 @@
-{% extends 'utilities/bulk_edit_form.html' %}
-{% load form_helpers %}
-
-{% block title %}Rack Bulk Edit{% endblock %}
-
-{% block selected_objects_table %}
-    <tr>
-        <th>Name</th>
-        <th>Site</th>
-        <th>Group</th>
-        <th>Tenant</th>
-        <th>Role</th>
-        <th>Type</th>
-        <th>Width</th>
-        <th>Height</th>
-    </tr>
-    {% for rack in selected_objects %}
-        <tr>
-            <td><a href="{% url 'dcim:rack' pk=rack.pk %}">{{ rack }}</a></td>
-            <td>{{ rack.site }}</td>
-            <td>{{ rack.group }}</td>
-            <td>{{ rack.tenant }}</td>
-            <td>{{ rack.role }}</td>
-            <td>{{ rack.get_type_display }}</td>
-            <td>{{ rack.get_width_display }}</td>
-            <td>{{ rack.u_height }}U</td>
-        </tr>
-    {% endfor %}
-{% endblock %}

+ 0 - 17
netbox/templates/dcim/site_bulk_edit.html

@@ -1,17 +0,0 @@
-{% extends 'utilities/bulk_edit_form.html' %}
-{% load form_helpers %}
-
-{% block title %}Site Bulk Edit{% endblock %}
-
-{% block selected_objects_table %}
-    <tr>
-        <th>Site</th>
-        <th>Tenant</th>
-    </tr>
-    {% for site in selected_objects %}
-        <tr>
-            <td><a href="{% url 'dcim:site' slug=site.slug %}">{{ site }}</a></td>
-            <td>{{ site.tenant }}</td>
-        </tr>
-    {% endfor %}
-{% endblock %}

+ 0 - 21
netbox/templates/ipam/aggregate_bulk_edit.html

@@ -1,21 +0,0 @@
-{% extends 'utilities/bulk_edit_form.html' %}
-{% load form_helpers %}
-
-{% block title %}Aggregate Bulk Edit{% endblock %}
-
-{% block selected_objects_table %}
-    <tr>
-        <th>Aggregate</th>
-        <th>RIR</th>
-        <th>Date Added</th>
-        <th>Description</th>
-    </tr>
-    {% for aggregate in selected_objects %}
-        <tr>
-            <td><a href="{% url 'ipam:aggregate' pk=aggregate.pk %}">{{ aggregate }}</a></td>
-            <td>{{ aggregate.rir }}</td>
-            <td>{{ aggregate.date_added }}</td>
-            <td>{{ aggregate.description }}</td>
-        </tr>
-    {% endfor %}
-{% endblock %}

+ 0 - 25
netbox/templates/ipam/ipaddress_bulk_edit.html

@@ -1,25 +0,0 @@
-{% extends 'utilities/bulk_edit_form.html' %}
-{% load form_helpers %}
-
-{% block title %}IP Address Bulk Edit{% endblock %}
-
-{% block selected_objects_table %}
-    <tr>
-        <th>IP Address</th>
-        <th>VRF</th>
-        <th>Tenant</th>
-        <th>Status</th>
-        <th>Assigned</th>
-        <th>Description</th>
-    </tr>
-    {% for ipaddress in selected_objects %}
-        <tr>
-            <td><a href="{% url 'ipam:ipaddress' pk=ipaddress.pk %}">{{ ipaddress }}</a></td>
-            <td>{{ ipaddress.vrf|default:"Global" }}</td>
-            <td>{{ ipaddress.tenant }}</td>
-            <td>{{ ipaddress.get_status_display }}</td>
-            <td>{% if ipaddress.interface %}<i class="glyphicon glyphicon-ok text-success" title="{{ ipaddress.interface.device }} {{ ipaddress.interface }}"></i>{% endif %}</td>
-            <td>{{ ipaddress.description }}</td>
-        </tr>
-    {% endfor %}
-{% endblock %}

+ 0 - 25
netbox/templates/ipam/prefix_bulk_edit.html

@@ -1,25 +0,0 @@
-{% extends 'utilities/bulk_edit_form.html' %}
-{% load form_helpers %}
-
-{% block title %}Prefix Bulk Edit{% endblock %}
-
-{% block selected_objects_table %}
-    <tr>
-        <th>Prefix</th>
-        <th>Site</th>
-        <th>VRF</th>
-        <th>Tenant</th>
-        <th>Status</th>
-        <th>Role</th>
-    </tr>
-    {% for prefix in selected_objects %}
-        <tr>
-            <td><a href="{% url 'ipam:prefix' pk=prefix.pk %}">{{ prefix }}</a></td>
-            <td>{{ prefix.site }}</td>
-            <td>{{ prefix.vrf|default:"Global" }}</td>
-            <td>{{ prefix.tenant }}</td>
-            <td>{{ prefix.get_status_display }}</td>
-            <td>{{ prefix.role }}</td>
-        </tr>
-    {% endfor %}
-{% endblock %}

+ 0 - 25
netbox/templates/ipam/vlan_bulk_edit.html

@@ -1,25 +0,0 @@
-{% extends 'utilities/bulk_edit_form.html' %}
-{% load form_helpers %}
-
-{% block title %}VLAN Bulk Edit{% endblock %}
-
-{% block selected_objects_table %}
-    <tr>
-        <th>VLAN</th>
-        <th>Site</th>
-        <th>Group</th>
-        <th>Tenant</th>
-        <th>Status</th>
-        <th>Role</th>
-    </tr>
-    {% for vlan in selected_objects %}
-        <tr>
-            <td><a href="{% url 'ipam:vlan' pk=vlan.pk %}">{{ vlan }}</a></td>
-            <td>{{ vlan.site }}</td>
-            <td>{{ vlan.group }}</td>
-            <td>{{ vlan.tenant }}</td>
-            <td>{{ vlan.get_status_display }}</td>
-            <td>{{ vlan.role }}</td>
-        </tr>
-    {% endfor %}
-{% endblock %}

+ 0 - 21
netbox/templates/ipam/vrf_bulk_edit.html

@@ -1,21 +0,0 @@
-{% extends 'utilities/bulk_edit_form.html' %}
-{% load form_helpers %}
-
-{% block title %}VRF Bulk Edit{% endblock %}
-
-{% block selected_objects_table %}
-    <tr>
-        <th>VRF</th>
-        <th>RD</th>
-        <th>Tenant</th>
-        <th>Description</th>
-    </tr>
-    {% for vrf in selected_objects %}
-        <tr>
-            <td><a href="{% url 'ipam:vrf' pk=vrf.pk %}">{{ vrf.name }}</a></td>
-            <td>{{ vrf.rd }}</td>
-            <td>{{ vrf.tenant }}</td>
-            <td>{{ vrf.description }}</td>
-        </tr>
-    {% endfor %}
-{% endblock %}

+ 0 - 19
netbox/templates/secrets/secret_bulk_edit.html

@@ -1,19 +0,0 @@
-{% extends 'utilities/bulk_edit_form.html' %}
-{% load form_helpers %}
-
-{% block title %}Secret Bulk Edit{% endblock %}
-
-{% block selected_objects_table %}
-    <tr>
-        <th>Device</th>
-        <th>Role</th>
-        <th>Name</th>
-    </tr>
-    {% for secret in selected_objects %}
-        <tr>
-            <td><a href="{% url 'secrets:secret' pk=secret.pk %}">{{ secret.device }}</a></td>
-            <td>{{ secret.role }}</td>
-            <td>{{ secret.name }}</td>
-        </tr>
-    {% endfor %}
-{% endblock %}

+ 0 - 17
netbox/templates/tenancy/tenant_bulk_edit.html

@@ -1,17 +0,0 @@
-{% extends 'utilities/bulk_edit_form.html' %}
-{% load form_helpers %}
-
-{% block title %}Tenant Bulk Edit{% endblock %}
-
-{% block selected_objects_table %}
-    <tr>
-        <th>Tenant</th>
-        <th>Group</th>
-    </tr>
-    {% for tenant in selected_objects %}
-        <tr>
-            <td><a href="{% url 'tenancy:tenant' slug=tenant.slug %}">{{ tenant }}</a></td>
-            <td>{{ tenant.group }}</td>
-        </tr>
-    {% endfor %}
-{% endblock %}

+ 0 - 19
netbox/templates/utilities/confirm_bulk_delete.html

@@ -1,19 +0,0 @@
-{% extends 'utilities/confirmation_form.html' %}
-{% load form_helpers %}
-
-{% block title %}Delete {{ obj_type_plural|default:"objects" }}?{% endblock %}
-
-{% block message %}
-    <p>
-        Are you sure you want to delete these {{ selected_objects|length }} {{ obj_type_plural|default:"objects" }}{% if parent_obj %} from <a href="{{ parent_obj.get_absolute_url }}">{{ parent_obj }}</a>{% endif %}?
-    </p>
-    <ul>
-        {% for obj in selected_objects %}
-            {% if obj.get_absolute_url %}
-                <li><a href="{{ obj.get_absolute_url }}">{{ obj }}</a></li>
-            {% else %}
-                <li>{{ obj }}</li>
-            {% endif %}
-        {% endfor %}
-    </ul>
-{% endblock %}

+ 38 - 0
netbox/templates/utilities/obj_bulk_delete.html

@@ -0,0 +1,38 @@
+{% extends '_base.html' %}
+{% load helpers %}
+
+{% block title %}Delete {{ table.rows|length }} {{ obj_type_plural|bettertitle }}?{% endblock %}
+
+{% block content %}
+    <div class="row">
+        <div class="col-md-8 col-md-offset-2">
+            <div class="panel panel-danger">
+                <div class="panel-heading"><strong>Confirm Bulk Deletion</strong></div>
+                <div class="panel-body">
+                    <strong>Warning:</strong> The following operation will delete {{ table.rows|length }} {{ obj_type_plural }}. Please carefully review the {{ obj_type_plural }} to be deleted and confirm below.
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="row">
+        <div class="col-md-8 col-md-offset-2">
+            <div class="panel panel-default">
+                {% include 'inc/table.html' %}
+            </div>
+        </div>
+    </div>
+    <div class="row">
+        <div class="col-md-6 col-md-offset-3">
+            <form action="." method="post" class="form">
+                {% csrf_token %}
+                {% for field in form.hidden_fields %}
+                    {{ field }}
+                {% endfor %}
+                <div class="text-center">
+                    <button type="submit" name="_confirm" class="btn btn-danger">Delete these {{ table.rows|length }} {{ obj_type_plural }}</button>
+                    <a href="{{ return_url }}" class="btn btn-default">Cancel</a>
+                </div>
+            </form>
+        </div>
+    </div>
+{% endblock %}

+ 5 - 7
netbox/templates/utilities/bulk_edit_form.html

@@ -1,8 +1,9 @@
 {% extends '_base.html' %}
+{% load helpers %}
 {% load form_helpers %}
 
 {% block content %}
-<h1>{% block title %}{% endblock %}</h1>
+<h1>{% block title %}Editing {{ table.rows|length }} {{ obj_type_plural|bettertitle }}{% endblock %}</h1>
 <form action="." method="post" class="form form-horizontal">
     {% csrf_token %}
     {% if request.POST.return_url %}
@@ -12,15 +13,12 @@
         {{ field }}
     {% endfor %}
     <div class="row">
-        <div class="col-md-7">
+        <div class="col-md-8">
             <div class="panel panel-default">
-                <div class="panel-heading"><strong>{% block selected_objects_title %}{{ selected_objects|length }} Selected For Editing{% endblock %}</strong></div>
-                <table class="panel-body table table-hover">
-                    {% block selected_objects_table %}{% endblock %}
-                </table>
+                {% include 'inc/table.html' %}
             </div>
         </div>
-        <div class="col-md-5">
+        <div class="col-md-4">
             {% if form.non_field_errors %}
                 <div class="panel panel-danger">
                     <div class="panel-heading"><strong>Errors</strong></div>

+ 1 - 1
netbox/tenancy/views.py

@@ -114,8 +114,8 @@ class TenantBulkEditView(PermissionRequiredMixin, BulkEditView):
     permission_required = 'tenancy.change_tenant'
     cls = Tenant
     filter = filters.TenantFilter
+    table = tables.TenantTable
     form = forms.TenantBulkEditForm
-    template_name = 'tenancy/tenant_bulk_edit.html'
     default_return_url = 'tenancy:tenant_list'
 
 

+ 13 - 8
netbox/utilities/views.py

@@ -462,6 +462,7 @@ class BulkEditView(View):
     cls: The model of the objects being edited
     parent_cls: The model of the parent object (if any)
     filter: FilterSet to apply when deleting by QuerySet
+    table: The table used to display devices being edited
     form: The form class used to edit objects in bulk
     template_name: The name of the template
     default_return_url: Name of the URL to which the user is redirected after editing the objects (can be overridden by
@@ -471,7 +472,8 @@ class BulkEditView(View):
     parent_cls = None
     filter = None
     form = None
-    template_name = None
+    table = None
+    template_name = 'utilities/obj_bulk_edit.html'
     default_return_url = 'home'
 
     def get(self):
@@ -537,14 +539,15 @@ class BulkEditView(View):
             initial_data['pk'] = pk_list
             form = self.form(self.cls, initial=initial_data)
 
-        selected_objects = self.cls.objects.filter(pk__in=pk_list)
-        if not selected_objects:
+        table = self.table(self.cls.objects.filter(pk__in=pk_list), orderable=False)
+        if not table.rows:
             messages.warning(request, "No {} were selected.".format(self.cls._meta.verbose_name_plural))
             return redirect(return_url)
 
         return render(request, self.template_name, {
             'form': form,
-            'selected_objects': selected_objects,
+            'table': table,
+            'obj_type_plural': self.cls._meta.verbose_name_plural,
             'return_url': return_url,
         })
 
@@ -603,6 +606,7 @@ class BulkDeleteView(View):
     cls: The model of the objects being deleted
     parent_cls: The model of the parent object (if any)
     filter: FilterSet to apply when deleting by QuerySet
+    table: The table used to display devices being deleted
     form: The form class used to delete objects in bulk
     template_name: The name of the template
     default_return_url: Name of the URL to which the user is redirected after deleting the objects (can be overriden by
@@ -611,8 +615,9 @@ class BulkDeleteView(View):
     cls = None
     parent_cls = None
     filter = None
+    table = None
     form = None
-    template_name = 'utilities/confirm_bulk_delete.html'
+    template_name = 'utilities/obj_bulk_delete.html'
     default_return_url = 'home'
 
     def post(self, request, **kwargs):
@@ -660,8 +665,8 @@ class BulkDeleteView(View):
         else:
             form = form_cls(initial={'pk': pk_list, 'return_url': return_url})
 
-        selected_objects = self.cls.objects.filter(pk__in=pk_list)
-        if not selected_objects:
+        table = self.table(self.cls.objects.filter(pk__in=pk_list), orderable=False)
+        if not table.rows:
             messages.warning(request, "No {} were selected for deletion.".format(self.cls._meta.verbose_name_plural))
             return redirect(return_url)
 
@@ -669,7 +674,7 @@ class BulkDeleteView(View):
             'form': form,
             'parent_obj': parent_obj,
             'obj_type_plural': self.cls._meta.verbose_name_plural,
-            'selected_objects': selected_objects,
+            'table': table,
             'return_url': return_url,
         })