diff --git a/netbox/circuits/views.py b/netbox/circuits/views.py
index 021709be1..4806fd954 100644
--- a/netbox/circuits/views.py
+++ b/netbox/circuits/views.py
@@ -127,6 +127,15 @@ class CircuitTypeListView(generic.ObjectListView):
class CircuitTypeView(generic.ObjectView):
queryset = CircuitType.objects.all()
+ def get_extra_context(self, request, instance):
+ related_models = (
+ (Circuit.objects.restrict(request.user, 'view').filter(type=instance), 'type_id'),
+ )
+
+ return {
+ 'related_models': related_models,
+ }
+
@register_model_view(CircuitType, 'edit')
class CircuitTypeEditView(generic.ObjectEditView):
diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py
index 077aa441e..693b7c2d2 100644
--- a/netbox/dcim/views.py
+++ b/netbox/dcim/views.py
@@ -543,6 +543,15 @@ class RackRoleListView(generic.ObjectListView):
class RackRoleView(generic.ObjectView):
queryset = RackRole.objects.all()
+ def get_extra_context(self, request, instance):
+ related_models = (
+ (Rack.objects.restrict(request.user, 'view').filter(role=instance), 'role_id'),
+ )
+
+ return {
+ 'related_models': related_models,
+ }
+
@register_model_view(RackRole, 'edit')
class RackRoleEditView(generic.ObjectEditView):
@@ -803,20 +812,15 @@ class ManufacturerView(generic.ObjectView):
queryset = Manufacturer.objects.all()
def get_extra_context(self, request, instance):
- device_types = DeviceType.objects.restrict(request.user, 'view').filter(
- manufacturer=instance
- )
- module_types = ModuleType.objects.restrict(request.user, 'view').filter(
- manufacturer=instance
- )
- inventory_items = InventoryItem.objects.restrict(request.user, 'view').filter(
- manufacturer=instance
+ related_models = (
+ (DeviceType.objects.restrict(request.user, 'view').filter(manufacturer=instance), 'manufacturer_id'),
+ (ModuleType.objects.restrict(request.user, 'view').filter(manufacturer=instance), 'manufacturer_id'),
+ (InventoryItem.objects.restrict(request.user, 'view').filter(manufacturer=instance), 'manufacturer_id'),
+ (Platform.objects.restrict(request.user, 'view').filter(manufacturer=instance), 'manufacturer_id'),
)
return {
- 'devicetype_count': device_types.count(),
- 'inventoryitem_count': inventory_items.count(),
- 'moduletype_count': module_types.count(),
+ 'related_models': related_models,
}
@@ -1667,41 +1671,15 @@ class DeviceRoleListView(generic.ObjectListView):
class DeviceRoleView(generic.ObjectView):
queryset = DeviceRole.objects.all()
+ def get_extra_context(self, request, instance):
+ related_models = (
+ (Device.objects.restrict(request.user, 'view').filter(device_role=instance), 'role_id'),
+ (VirtualMachine.objects.restrict(request.user, 'view').filter(role=instance), 'role_id'),
+ )
-@register_model_view(DeviceRole, 'devices', path='devices')
-class DeviceRoleDevicesView(generic.ObjectChildrenView):
- queryset = DeviceRole.objects.all()
- child_model = Device
- table = tables.DeviceTable
- filterset = filtersets.DeviceFilterSet
- template_name = 'dcim/devicerole/devices.html'
- tab = ViewTab(
- label=_('Devices'),
- badge=lambda obj: obj.devices.count(),
- permission='dcim.view_device',
- weight=400
- )
-
- def get_children(self, request, parent):
- return Device.objects.restrict(request.user, 'view').filter(device_role=parent)
-
-
-@register_model_view(DeviceRole, 'virtual_machines', path='virtual-machines')
-class DeviceRoleVirtualMachinesView(generic.ObjectChildrenView):
- queryset = DeviceRole.objects.all()
- child_model = VirtualMachine
- table = VirtualMachineTable
- filterset = VirtualMachineFilterSet
- template_name = 'dcim/devicerole/virtual_machines.html'
- tab = ViewTab(
- label=_('Virtual machines'),
- badge=lambda obj: obj.virtual_machines.count(),
- permission='virtualization.view_virtualmachine',
- weight=500
- )
-
- def get_children(self, request, parent):
- return VirtualMachine.objects.restrict(request.user, 'view').filter(role=parent)
+ return {
+ 'related_models': related_models,
+ }
@register_model_view(DeviceRole, 'edit')
@@ -1758,16 +1736,13 @@ class PlatformView(generic.ObjectView):
queryset = Platform.objects.all()
def get_extra_context(self, request, instance):
- devices = Device.objects.restrict(request.user, 'view').filter(
- platform=instance
- )
- virtual_machines = VirtualMachine.objects.restrict(request.user, 'view').filter(
- platform=instance
+ related_models = (
+ (Device.objects.restrict(request.user, 'view').filter(platform=instance), 'platform_id'),
+ (VirtualMachine.objects.restrict(request.user, 'view').filter(platform=instance), 'platform_id'),
)
return {
- 'device_count': devices.count(),
- 'virtualmachine_count': virtual_machines.count()
+ 'related_models': related_models,
}
diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py
index 9741be66b..bcafacc45 100644
--- a/netbox/ipam/views.py
+++ b/netbox/ipam/views.py
@@ -165,6 +165,15 @@ class RIRListView(generic.ObjectListView):
class RIRView(generic.ObjectView):
queryset = RIR.objects.all()
+ def get_extra_context(self, request, instance):
+ related_models = (
+ (Aggregate.objects.restrict(request.user, 'view').filter(rir=instance), 'rir_id'),
+ )
+
+ return {
+ 'related_models': related_models,
+ }
+
@register_model_view(RIR, 'edit')
class RIREditView(generic.ObjectEditView):
@@ -368,6 +377,17 @@ class RoleListView(generic.ObjectListView):
class RoleView(generic.ObjectView):
queryset = Role.objects.all()
+ def get_extra_context(self, request, instance):
+ related_models = (
+ (Prefix.objects.restrict(request.user, 'view').filter(role=instance), 'role_id'),
+ (IPRange.objects.restrict(request.user, 'view').filter(role=instance), 'role_id'),
+ (VLAN.objects.restrict(request.user, 'view').filter(role=instance), 'role_id'),
+ )
+
+ return {
+ 'related_models': related_models,
+ }
+
@register_model_view(Role, 'edit')
class RoleEditView(generic.ObjectEditView):
@@ -839,6 +859,11 @@ class VLANGroupView(generic.ObjectView):
queryset = VLANGroup.objects.all()
def get_extra_context(self, request, instance):
+ related_models = (
+ (VLAN.objects.restrict(request.user, 'view').filter(group=instance), 'group_id'),
+ )
+
+ # TODO: Replace with embedded table
vlans = VLAN.objects.restrict(request.user, 'view').filter(group=instance).prefetch_related(
Prefetch('prefixes', queryset=Prefix.objects.restrict(request.user)),
'tenant', 'site', 'role',
@@ -852,7 +877,7 @@ class VLANGroupView(generic.ObjectView):
vlans_table.configure(request)
return {
- 'vlans_count': vlans_count,
+ 'related_models': related_models,
'vlans_table': vlans_table,
}
diff --git a/netbox/templates/circuits/circuittype.html b/netbox/templates/circuits/circuittype.html
index 4cefecc87..3d5ba5a6c 100644
--- a/netbox/templates/circuits/circuittype.html
+++ b/netbox/templates/circuits/circuittype.html
@@ -28,12 +28,6 @@
Description |
{{ object.description|placeholder }} |
-
- Circuits |
-
- {{ object.circuits.count }}
- |
-
@@ -41,19 +35,13 @@
{% plugin_left_page object %}
+ {% include 'inc/panels/related_objects.html' %}
{% include 'inc/panels/custom_fields.html' %}
{% plugin_right_page object %}
-
{% plugin_full_width_page object %}
diff --git a/netbox/templates/dcim/devicerole.html b/netbox/templates/dcim/devicerole.html
index 2e0794582..bc01dbdb7 100644
--- a/netbox/templates/dcim/devicerole.html
+++ b/netbox/templates/dcim/devicerole.html
@@ -42,22 +42,6 @@
VM Role |
{% checkmark object.vm_role %} |
-
- Devices |
-
- {{ object.devices.count }}
- |
-
-
- Virtual Machines |
-
- {% if object.vm_role %}
- {{ object.virtual_machines.count }}
- {% else %}
- {{ ''|placeholder }}
- {% endif %}
- |
-
@@ -65,6 +49,7 @@
{% plugin_left_page object %}
+ {% include 'inc/panels/related_objects.html' %}
{% include 'inc/panels/custom_fields.html' %}
{% plugin_right_page object %}
diff --git a/netbox/templates/dcim/devicerole/devices.html b/netbox/templates/dcim/devicerole/devices.html
deleted file mode 100644
index d7a69f013..000000000
--- a/netbox/templates/dcim/devicerole/devices.html
+++ /dev/null
@@ -1,20 +0,0 @@
-{% extends 'dcim/devicerole.html' %}
-{% load helpers %}
-{% load render_table from django_tables2 %}
-
-{% block content %}
- {% include 'inc/table_controls_htmx.html' with table_modal='DeviceTable_config' %}
-
-{% endblock content %}
-
-{% block modals %}
- {{ block.super }}
- {% table_config_form table %}
-{% endblock modals %}
\ No newline at end of file
diff --git a/netbox/templates/dcim/devicerole/virtual_machines.html b/netbox/templates/dcim/devicerole/virtual_machines.html
deleted file mode 100644
index d94e86839..000000000
--- a/netbox/templates/dcim/devicerole/virtual_machines.html
+++ /dev/null
@@ -1,20 +0,0 @@
-{% extends 'dcim/devicerole.html' %}
-{% load helpers %}
-{% load render_table from django_tables2 %}
-
-{% block content %}
- {% include 'inc/table_controls_htmx.html' with table_modal='VirtualMachineTable_config' %}
-
-{% endblock content %}
-
-{% block modals %}
- {{ block.super }}
- {% table_config_form table %}
-{% endblock modals %}
\ No newline at end of file
diff --git a/netbox/templates/dcim/manufacturer.html b/netbox/templates/dcim/manufacturer.html
index 260f8e39a..a60b3503c 100644
--- a/netbox/templates/dcim/manufacturer.html
+++ b/netbox/templates/dcim/manufacturer.html
@@ -42,24 +42,6 @@
Description |
{{ object.description|placeholder }} |
-
- Device types |
-
- {{ devicetype_count }}
- |
-
-
- Module types |
-
- {{ moduletype_count }}
- |
-
-
- Inventory Items |
-
- {{ inventoryitem_count }}
- |
-
@@ -67,6 +49,7 @@
{% plugin_left_page object %}
+ {% include 'inc/panels/related_objects.html' %}
{% include 'inc/panels/custom_fields.html' %}
{% include 'inc/panels/contacts.html' %}
{% plugin_right_page object %}
@@ -74,13 +57,6 @@
-
{% plugin_full_width_page object %}
diff --git a/netbox/templates/dcim/platform.html b/netbox/templates/dcim/platform.html
index f134ac649..17a313d82 100644
--- a/netbox/templates/dcim/platform.html
+++ b/netbox/templates/dcim/platform.html
@@ -43,46 +43,26 @@
NAPALM Driver |
{{ object.napalm_driver|placeholder }} |
-
- Devices |
-
- {{ device_count }}
- |
-
-
- Virtual Machines |
-
- {{ virtualmachine_count }}
- |
-
{% include 'inc/panels/tags.html' %}
- {% plugin_left_page object %}
-
-
-
+
{{ object.napalm_args|json }}
+ {% plugin_left_page object %}
+
+
+ {% include 'inc/panels/related_objects.html' %}
{% include 'inc/panels/custom_fields.html' %}
{% plugin_right_page object %}
-
{% plugin_full_width_page object %}
diff --git a/netbox/templates/dcim/rackrole.html b/netbox/templates/dcim/rackrole.html
index 0f229e910..2d2945025 100644
--- a/netbox/templates/dcim/rackrole.html
+++ b/netbox/templates/dcim/rackrole.html
@@ -34,12 +34,6 @@
-
- Racks |
-
- {{ object.racks.count }}
- |
-
@@ -47,19 +41,13 @@
{% plugin_left_page object %}
+ {% include 'inc/panels/related_objects.html' %}
{% include 'inc/panels/custom_fields.html' %}
{% plugin_right_page object %}
-
{% plugin_full_width_page object %}
diff --git a/netbox/templates/ipam/rir.html b/netbox/templates/ipam/rir.html
index a0355b99c..35b3c6b06 100644
--- a/netbox/templates/ipam/rir.html
+++ b/netbox/templates/ipam/rir.html
@@ -32,32 +32,20 @@
Private |
{% checkmark object.is_private %} |
-
- Aggregates |
-
- {{ object.aggregates.count }}
- |
-
+ {% include 'inc/panels/tags.html' %}
{% plugin_left_page object %}
- {% include 'inc/panels/tags.html' %}
+ {% include 'inc/panels/related_objects.html' %}
{% include 'inc/panels/custom_fields.html' %}
{% plugin_right_page object %}
-
{% plugin_full_width_page object %}
diff --git a/netbox/templates/ipam/role.html b/netbox/templates/ipam/role.html
index 1018824e9..12b73c1a9 100644
--- a/netbox/templates/ipam/role.html
+++ b/netbox/templates/ipam/role.html
@@ -32,44 +32,20 @@
Weight |
{{ object.weight }} |
-
- Prefixes |
-
- {{ object.prefixes.count }}
- |
-
-
- IP Ranges |
-
- {{ object.ip_ranges.count }}
- |
-
-
- VLANs |
-
- {{ object.vlans.count }}
- |
-
+ {% include 'inc/panels/tags.html' %}
{% plugin_left_page object %}
- {% include 'inc/panels/tags.html' %}
+ {% include 'inc/panels/related_objects.html' %}
{% include 'inc/panels/custom_fields.html' %}
{% plugin_right_page object %}
-
{% plugin_full_width_page object %}
diff --git a/netbox/templates/ipam/vlangroup.html b/netbox/templates/ipam/vlangroup.html
index 822b4a046..2917536be 100644
--- a/netbox/templates/ipam/vlangroup.html
+++ b/netbox/templates/ipam/vlangroup.html
@@ -42,12 +42,6 @@
Permitted VIDs |
{{ object.min_vid }} - {{ object.max_vid }} |
-
- VLANs |
-
- {{ vlans_count }}
- |
-
@@ -55,6 +49,7 @@
{% plugin_left_page object %}
+ {% include 'inc/panels/related_objects.html' %}
{% include 'inc/panels/custom_fields.html' %}
{% plugin_right_page object %}
diff --git a/netbox/templates/virtualization/clustergroup.html b/netbox/templates/virtualization/clustergroup.html
index 7d7d5a677..510433068 100644
--- a/netbox/templates/virtualization/clustergroup.html
+++ b/netbox/templates/virtualization/clustergroup.html
@@ -28,12 +28,6 @@
Description |
{{ object.description|placeholder }} |
-
- Clusters |
-
- {{ object.clusters.count }}
- |
-
@@ -41,6 +35,7 @@
{% plugin_left_page object %}
+ {% include 'inc/panels/related_objects.html' %}
{% include 'inc/panels/custom_fields.html' %}
{% include 'inc/panels/contacts.html' %}
{% plugin_right_page object %}
@@ -48,13 +43,6 @@
-
{% plugin_full_width_page object %}
diff --git a/netbox/templates/virtualization/clustertype.html b/netbox/templates/virtualization/clustertype.html
index 5a5379160..2881fc1da 100644
--- a/netbox/templates/virtualization/clustertype.html
+++ b/netbox/templates/virtualization/clustertype.html
@@ -41,19 +41,13 @@
{% plugin_left_page object %}
+ {% include 'inc/panels/related_objects.html' %}
{% include 'inc/panels/custom_fields.html' %}
{% plugin_right_page object %}
-
{% plugin_full_width_page object %}
diff --git a/netbox/virtualization/views.py b/netbox/virtualization/views.py
index bbb46face..d7a4856f2 100644
--- a/netbox/virtualization/views.py
+++ b/netbox/virtualization/views.py
@@ -10,7 +10,7 @@ from dcim.models import Device
from dcim.tables import DeviceTable
from extras.views import ObjectConfigContextView
from ipam.models import IPAddress, Service
-from ipam.tables import AssignedIPAddressesTable, InterfaceVLANTable
+from ipam.tables import InterfaceVLANTable
from netbox.views import generic
from utilities.utils import count_related
from utilities.views import ViewTab, register_model_view
@@ -36,17 +36,12 @@ class ClusterTypeView(generic.ObjectView):
queryset = ClusterType.objects.all()
def get_extra_context(self, request, instance):
- clusters = Cluster.objects.restrict(request.user, 'view').filter(
- type=instance
- ).annotate(
- device_count=count_related(Device, 'cluster'),
- vm_count=count_related(VirtualMachine, 'cluster')
+ related_models = (
+ (Cluster.objects.restrict(request.user, 'view').filter(type=instance), 'type_id'),
)
- clusters_table = tables.ClusterTable(clusters, user=request.user, exclude=('type',))
- clusters_table.configure(request)
return {
- 'clusters_table': clusters_table,
+ 'related_models': related_models,
}
@@ -100,6 +95,15 @@ class ClusterGroupListView(generic.ObjectListView):
class ClusterGroupView(generic.ObjectView):
queryset = ClusterGroup.objects.all()
+ def get_extra_context(self, request, instance):
+ related_models = (
+ (Cluster.objects.restrict(request.user, 'view').filter(group=instance), 'group_id'),
+ )
+
+ return {
+ 'related_models': related_models,
+ }
+
@register_model_view(ClusterGroup, 'edit')
class ClusterGroupEditView(generic.ObjectEditView):