diff --git a/netbox/circuits/views.py b/netbox/circuits/views.py
index 4806fd954..228b70bb1 100644
--- a/netbox/circuits/views.py
+++ b/netbox/circuits/views.py
@@ -29,6 +29,15 @@ class ProviderListView(generic.ObjectListView):
class ProviderView(generic.ObjectView):
queryset = Provider.objects.all()
+ def get_extra_context(self, request, instance):
+ related_models = (
+ (Circuit.objects.restrict(request.user, 'view').filter(provider=instance), 'provider_id'),
+ )
+
+ return {
+ 'related_models': related_models,
+ }
+
@register_model_view(Provider, 'edit')
class ProviderEditView(generic.ObjectEditView):
@@ -79,6 +88,18 @@ class ProviderNetworkListView(generic.ObjectListView):
class ProviderNetworkView(generic.ObjectView):
queryset = ProviderNetwork.objects.all()
+ def get_extra_context(self, request, instance):
+ related_models = (
+ (
+ Circuit.objects.restrict(request.user, 'view').filter(terminations__provider_network=instance),
+ 'providernetwork_id',
+ ),
+ )
+
+ return {
+ 'related_models': related_models,
+ }
+
@register_model_view(ProviderNetwork, 'edit')
class ProviderNetworkEditView(generic.ObjectEditView):
diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py
index 4683a6084..741194712 100644
--- a/netbox/dcim/views.py
+++ b/netbox/dcim/views.py
@@ -21,9 +21,7 @@ from utilities.paginator import EnhancedPaginator, get_paginate_count
from utilities.permissions import get_permission_for_model
from utilities.utils import count_related
from utilities.views import GetReturnURLMixin, ObjectPermissionRequiredMixin, ViewTab, register_model_view
-from virtualization.filtersets import VirtualMachineFilterSet
from virtualization.models import VirtualMachine
-from virtualization.tables import VirtualMachineTable
from . import filtersets, forms, tables
from .choices import DeviceFaceChoices
from .constants import NONCONNECTABLE_IFACE_TYPES
@@ -359,24 +357,24 @@ class SiteView(generic.ObjectView):
queryset = Site.objects.prefetch_related('tenant__group')
def get_extra_context(self, request, instance):
- related_models = [
+ related_models = (
# DCIM
- Location.objects.restrict(request.user, 'view').filter(site=instance),
- Rack.objects.restrict(request.user, 'view').filter(site=instance),
- Device.objects.restrict(request.user, 'view').filter(site=instance),
+ (Location.objects.restrict(request.user, 'view').filter(site=instance), 'site_id'),
+ (Rack.objects.restrict(request.user, 'view').filter(site=instance), 'site_id'),
+ (Device.objects.restrict(request.user, 'view').filter(site=instance), 'site_id'),
# Virtualization
- VirtualMachine.objects.restrict(request.user, 'view').filter(cluster__site=instance),
+ (VirtualMachine.objects.restrict(request.user, 'view').filter(cluster__site=instance), 'site_id'),
# IPAM
- Prefix.objects.restrict(request.user, 'view').filter(site=instance),
- ASN.objects.restrict(request.user, 'view').filter(sites=instance),
- VLANGroup.objects.restrict(request.user, 'view').filter(
+ (Prefix.objects.restrict(request.user, 'view').filter(site=instance), 'site_id'),
+ (ASN.objects.restrict(request.user, 'view').filter(sites=instance), 'site_id'),
+ (VLANGroup.objects.restrict(request.user, 'view').filter(
scope_type=ContentType.objects.get_for_model(Site),
scope_id=instance.pk
- ),
- VLAN.objects.restrict(request.user, 'view').filter(site=instance),
+ ), 'site_id'),
+ (VLAN.objects.restrict(request.user, 'view').filter(site=instance), 'site_id'),
# Circuits
- Circuit.objects.restrict(request.user, 'view').filter(terminations__site=instance).distinct(),
- ]
+ (Circuit.objects.restrict(request.user, 'view').filter(terminations__site=instance).distinct(), 'site_id'),
+ )
locations = Location.objects.add_related_count(
Location.objects.all(),
@@ -658,6 +656,11 @@ class RackView(generic.ObjectView):
queryset = Rack.objects.prefetch_related('site__region', 'tenant__group', 'location', 'role')
def get_extra_context(self, request, instance):
+ related_models = (
+ (Device.objects.restrict(request.user, 'view').filter(rack=instance), 'rack_id'),
+ (PowerFeed.objects.restrict(request.user).filter(rack=instance), 'rack_id'),
+ )
+
# Get 0U devices located within the rack
nonracked_devices = Device.objects.filter(
rack=instance,
@@ -675,11 +678,6 @@ class RackView(generic.ObjectView):
prev_rack = peer_racks.filter(_name__lt=instance._name).reverse().first()
reservations = RackReservation.objects.restrict(request.user, 'view').filter(rack=instance)
- power_feeds = PowerFeed.objects.restrict(request.user, 'view').filter(rack=instance).prefetch_related(
- 'power_panel'
- )
-
- device_count = Device.objects.restrict(request.user, 'view').filter(rack=instance).count()
# Determine any additional parameters to pass when embedding the rack elevations
svg_extra = '&'.join([
@@ -687,9 +685,8 @@ class RackView(generic.ObjectView):
])
return {
- 'device_count': device_count,
+ 'related_models': related_models,
'reservations': reservations,
- 'power_feeds': power_feeds,
'nonracked_devices': nonracked_devices,
'next_rack': next_rack,
'prev_rack': prev_rack,
@@ -881,10 +878,12 @@ class DeviceTypeView(generic.ObjectView):
queryset = DeviceType.objects.all()
def get_extra_context(self, request, instance):
- instance_count = Device.objects.restrict(request.user).filter(device_type=instance).count()
+ related_models = (
+ (Device.objects.restrict(request.user).filter(device_type=instance), 'device_type_id'),
+ )
return {
- 'instance_count': instance_count,
+ 'related_models': related_models,
}
@@ -1119,10 +1118,12 @@ class ModuleTypeView(generic.ObjectView):
queryset = ModuleType.objects.all()
def get_extra_context(self, request, instance):
- instance_count = Module.objects.restrict(request.user).filter(module_type=instance).count()
+ related_models = (
+ (Module.objects.restrict(request.user).filter(module_type=instance), 'module_type_id'),
+ )
return {
- 'instance_count': instance_count,
+ 'related_models': related_models,
}
@@ -1807,13 +1808,9 @@ class DeviceView(generic.ObjectView):
vc_members = []
services = Service.objects.restrict(request.user, 'view').filter(device=instance)
- vdcs = VirtualDeviceContext.objects.restrict(request.user, 'view').filter(device=instance).prefetch_related(
- 'tenant'
- )
return {
'services': services,
- 'vdcs': vdcs,
'vc_members': vc_members,
'svg_extra': f'highlight=id:{instance.pk}'
}
@@ -2114,6 +2111,21 @@ class ModuleListView(generic.ObjectListView):
class ModuleView(generic.ObjectView):
queryset = Module.objects.all()
+ def get_extra_context(self, request, instance):
+ related_models = (
+ (Interface.objects.restrict(request.user, 'view').filter(module=instance), 'module_id'),
+ (ConsolePort.objects.restrict(request.user, 'view').filter(module=instance), 'module_id'),
+ (ConsoleServerPort.objects.restrict(request.user, 'view').filter(module=instance), 'module_id'),
+ (PowerPort.objects.restrict(request.user, 'view').filter(module=instance), 'module_id'),
+ (PowerOutlet.objects.restrict(request.user, 'view').filter(module=instance), 'module_id'),
+ (FrontPort.objects.restrict(request.user, 'view').filter(module=instance), 'module_id'),
+ (RearPort.objects.restrict(request.user, 'view').filter(module=instance), 'module_id'),
+ )
+
+ return {
+ 'related_models': related_models,
+ }
+
@register_model_view(Module, 'edit')
class ModuleEditView(generic.ObjectEditView):
@@ -3436,6 +3448,15 @@ class PowerPanelListView(generic.ObjectListView):
class PowerPanelView(generic.ObjectView):
queryset = PowerPanel.objects.all()
+ def get_extra_context(self, request, instance):
+ related_models = (
+ (PowerFeed.objects.restrict(request.user).filter(power_panel=instance), 'power_panel_id'),
+ )
+
+ return {
+ 'related_models': related_models,
+ }
+
@register_model_view(PowerPanel, 'edit')
class PowerPanelEditView(generic.ObjectEditView):
@@ -3537,6 +3558,15 @@ class VirtualDeviceContextListView(generic.ObjectListView):
class VirtualDeviceContextView(generic.ObjectView):
queryset = VirtualDeviceContext.objects.all()
+ def get_extra_context(self, request, instance):
+ related_models = (
+ (Interface.objects.restrict(request.user, 'view').filter(vdcs__in=[instance]), 'vdc_id'),
+ )
+
+ return {
+ 'related_models': related_models,
+ }
+
@register_model_view(VirtualDeviceContext, 'edit')
class VirtualDeviceContextEditView(generic.ObjectEditView):
diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py
index bcafacc45..b7cd72d67 100644
--- a/netbox/ipam/views.py
+++ b/netbox/ipam/views.py
@@ -37,8 +37,10 @@ class VRFView(generic.ObjectView):
queryset = VRF.objects.all()
def get_extra_context(self, request, instance):
- prefix_count = Prefix.objects.restrict(request.user, 'view').filter(vrf=instance).count()
- ipaddress_count = IPAddress.objects.restrict(request.user, 'view').filter(vrf=instance).count()
+ related_models = (
+ (Prefix.objects.restrict(request.user, 'view').filter(vrf=instance), 'vrf_id'),
+ (IPAddress.objects.restrict(request.user, 'view').filter(vrf=instance), 'vrf_id'),
+ )
import_targets_table = tables.RouteTargetTable(
instance.import_targets.all(),
@@ -50,8 +52,7 @@ class VRFView(generic.ObjectView):
)
return {
- 'prefix_count': prefix_count,
- 'ipaddress_count': ipaddress_count,
+ 'related_models': related_models,
'import_targets_table': import_targets_table,
'export_targets_table': export_targets_table,
}
@@ -228,12 +229,13 @@ class ASNView(generic.ObjectView):
queryset = ASN.objects.all()
def get_extra_context(self, request, instance):
- sites = instance.sites.restrict(request.user, 'view')
- providers = instance.providers.restrict(request.user, 'view')
+ related_models = (
+ (Site.objects.restrict(request.user, 'view').filter(asns__in=[instance]), 'asn_id'),
+ (Provider.objects.restrict(request.user, 'view').filter(asns__in=[instance]), 'asn_id'),
+ )
return {
- 'sites_count': sites.count(),
- 'providers_count': providers.count(),
+ 'related_models': related_models,
}
@@ -868,7 +870,6 @@ class VLANGroupView(generic.ObjectView):
Prefetch('prefixes', queryset=Prefix.objects.restrict(request.user)),
'tenant', 'site', 'role',
).order_by('vid')
- vlans_count = vlans.count()
vlans = add_available_vlans(vlans, vlan_group=instance)
vlans_table = tables.VLANTable(vlans, user=request.user, exclude=('group',))
diff --git a/netbox/templates/circuits/circuittype.html b/netbox/templates/circuits/circuittype.html
index 3d5ba5a6c..39c1f1541 100644
--- a/netbox/templates/circuits/circuittype.html
+++ b/netbox/templates/circuits/circuittype.html
@@ -35,7 +35,7 @@
{% plugin_left_page object %}
- {% include 'inc/panels/related_objects.html' %}
+ {% include 'inc/panels/related_objects.html' %}
{% include 'inc/panels/custom_fields.html' %}
{% plugin_right_page object %}
diff --git a/netbox/templates/circuits/provider.html b/netbox/templates/circuits/provider.html
index 8cd7e59fb..3973d2867 100644
--- a/netbox/templates/circuits/provider.html
+++ b/netbox/templates/circuits/provider.html
@@ -37,21 +37,16 @@
Description |
{{ object.description|placeholder }} |
-
- Circuits |
-
- {{ object.circuits.count }}
- |
-
{% include 'inc/panels/tags.html' %}
+ {% include 'inc/panels/comments.html' %}
{% plugin_left_page object %}
+ {% include 'inc/panels/related_objects.html' %}
{% include 'inc/panels/custom_fields.html' %}
- {% include 'inc/panels/comments.html' %}
{% include 'inc/panels/contacts.html' %}
{% plugin_right_page object %}
diff --git a/netbox/templates/circuits/providernetwork.html b/netbox/templates/circuits/providernetwork.html
index 29c31ab47..f478058ec 100644
--- a/netbox/templates/circuits/providernetwork.html
+++ b/netbox/templates/circuits/providernetwork.html
@@ -37,12 +37,13 @@
+ {% include 'inc/panels/tags.html' %}
{% plugin_left_page object %}
- {% include 'inc/panels/custom_fields.html' %}
- {% include 'inc/panels/tags.html' %}
+ {% include 'inc/panels/related_objects.html' %}
{% include 'inc/panels/comments.html' %}
+ {% include 'inc/panels/custom_fields.html' %}
{% plugin_right_page object %}
diff --git a/netbox/templates/dcim/device.html b/netbox/templates/dcim/device.html
index aa31db97c..6a0d00d6d 100644
--- a/netbox/templates/dcim/device.html
+++ b/netbox/templates/dcim/device.html
@@ -157,28 +157,10 @@
{% include 'inc/panels/comments.html' %}
-
- {% if vdcs %}
-
-
- Name |
- Status |
- Identifier |
- Tenant |
-
- {% for vdc in vdcs %}
-
- {{ vdc|linkify }} |
- {% badge vdc.get_status_display bg_color=vdc.get_status_color %} |
- {{ vdc.identifier|placeholder }} |
- {{ vdc.tenant|linkify|placeholder }} |
-
- {% endfor %}
-
- {% else %}
-
None
- {% endif %}
-
+
{% if perms.dcim.add_virtualdevicecontext %}
+ {% include 'inc/panels/tags.html' %}
{% plugin_left_page object %}
+ {% include 'inc/panels/related_objects.html' %}
{% include 'inc/panels/custom_fields.html' %}
- {% include 'inc/panels/tags.html' %}
{% include 'inc/panels/comments.html' %}
{% plugin_right_page object %}
diff --git a/netbox/templates/dcim/module.html b/netbox/templates/dcim/module.html
index 78d5a1a05..e46bc65f5 100644
--- a/netbox/templates/dcim/module.html
+++ b/netbox/templates/dcim/module.html
@@ -81,104 +81,14 @@
- {% include 'inc/panels/custom_fields.html' %}
{% include 'inc/panels/tags.html' %}
{% include 'inc/panels/comments.html' %}
{% plugin_left_page object %}
-
-
-
-
-
-
-
- Interfaces |
-
- {% with component_count=object.interfaces.count %}
- {% if component_count %}
- {{ component_count }}
- {% else %}
- {{ ''|placeholder }}
- {% endif %}
- {% endwith %}
- |
-
-
- Console Ports |
-
- {% with component_count=object.consoleports.count %}
- {% if component_count %}
- {{ component_count }}
- {% else %}
- {{ ''|placeholder }}
- {% endif %}
- {% endwith %}
- |
-
-
- Console Server Ports |
-
- {% with component_count=object.consoleserverports.count %}
- {% if component_count %}
- {{ component_count }}
- {% else %}
- {{ ''|placeholder }}
- {% endif %}
- {% endwith %}
- |
-
-
- Power Ports |
-
- {% with component_count=object.powerports.count %}
- {% if component_count %}
- {{ component_count }}
- {% else %}
- {{ ''|placeholder }}
- {% endif %}
- {% endwith %}
- |
-
-
- Power Outlets |
-
- {% with component_count=object.poweroutlets.count %}
- {% if component_count %}
- {{ component_count }}
- {% else %}
- {{ ''|placeholder }}
- {% endif %}
- {% endwith %}
- |
-
-
- Front Ports |
-
- {% with component_count=object.frontports.count %}
- {% if component_count %}
- {{ component_count }}
- {% else %}
- {{ ''|placeholder }}
- {% endif %}
- {% endwith %}
- |
-
-
- Rear Ports |
-
- {% with component_count=object.rearports.count %}
- {% if component_count %}
- {{ component_count }}
- {% else %}
- {{ ''|placeholder }}
- {% endif %}
- {% endwith %}
- |
-
-
-
-
- {% plugin_right_page object %}
+
+
+ {% include 'inc/panels/related_objects.html' %}
+ {% include 'inc/panels/custom_fields.html' %}
+ {% plugin_right_page object %}
diff --git a/netbox/templates/dcim/moduletype.html b/netbox/templates/dcim/moduletype.html
index fd0148c2f..8929678b7 100644
--- a/netbox/templates/dcim/moduletype.html
+++ b/netbox/templates/dcim/moduletype.html
@@ -36,19 +36,16 @@
{% endif %}
-
- Instances |
- {{ instance_count }} |
-
- {% include 'inc/panels/custom_fields.html' %}
+ {% include 'inc/panels/tags.html' %}
+ {% include 'inc/panels/comments.html' %}
{% plugin_left_page object %}
- {% include 'inc/panels/tags.html' %}
- {% include 'inc/panels/comments.html' %}
+ {% include 'inc/panels/related_objects.html' %}
+ {% include 'inc/panels/custom_fields.html' %}
{% include 'inc/panels/image_attachments.html' %}
{% plugin_right_page object %}
diff --git a/netbox/templates/dcim/powerpanel.html b/netbox/templates/dcim/powerpanel.html
index c73e33b13..af08f3023 100644
--- a/netbox/templates/dcim/powerpanel.html
+++ b/netbox/templates/dcim/powerpanel.html
@@ -38,11 +38,12 @@
{% plugin_left_page object %}
- {% include 'inc/panels/custom_fields.html' %}
- {% include 'inc/panels/contacts.html' %}
- {% include 'inc/panels/image_attachments.html' %}
- {% plugin_right_page object %}
-
+ {% include 'inc/panels/related_objects.html' %}
+ {% include 'inc/panels/custom_fields.html' %}
+ {% include 'inc/panels/contacts.html' %}
+ {% include 'inc/panels/image_attachments.html' %}
+ {% plugin_right_page object %}
+
diff --git a/netbox/templates/dcim/rack.html b/netbox/templates/dcim/rack.html
index e2cb1597e..c155f2796 100644
--- a/netbox/templates/dcim/rack.html
+++ b/netbox/templates/dcim/rack.html
@@ -90,12 +90,6 @@
Asset Tag |
{{ object.asset_tag|placeholder }} |
-
- Devices |
-
- {{ device_count }}
- |
-
Space Utilization |
{% utilization_graph object.get_utilization %} |
@@ -192,40 +186,6 @@
{% include 'inc/panels/custom_fields.html' %}
{% include 'inc/panels/tags.html' %}
{% include 'inc/panels/comments.html' %}
- {% if power_feeds %}
-
-
-
-
-
- Panel |
- Feed |
- Status |
- Type |
- Utilization |
-
- {% for powerfeed in power_feeds %}
-
- {{ powerfeed.power_panel|linkify }} |
- {{ powerfeed|linkify }} |
- {% badge powerfeed.get_status_display bg_color=powerfeed.get_status_color %} |
- {% badge powerfeed.get_type_display bg_color=powerfeed.get_type_color %} |
- {% with power_port=powerfeed.connected_endpoints.0 %}
- {% if power_port %}
- {% utilization_graph power_port.get_power_draw.allocated|percentage:powerfeed.available_power %} |
- {% else %}
- N/A |
- {% endif %}
- {% endwith %}
-
- {% endfor %}
-
-
-
- {% endif %}
-
{% include 'inc/panels/image_attachments.html' %}
+ {% include 'inc/panels/related_objects.html' %}
{% include 'dcim/inc/nonracked_devices.html' %}
{% include 'inc/panels/contacts.html' %}
{% plugin_right_page object %}
diff --git a/netbox/templates/dcim/virtualdevicecontext.html b/netbox/templates/dcim/virtualdevicecontext.html
index ee30db19e..d6e3e0c63 100644
--- a/netbox/templates/dcim/virtualdevicecontext.html
+++ b/netbox/templates/dcim/virtualdevicecontext.html
@@ -59,10 +59,11 @@
{% plugin_left_page object %}
+ {% include 'inc/panels/tags.html' %}
+ {% include 'inc/panels/related_objects.html' %}
{% include 'inc/panels/comments.html' %}
- {% include 'inc/panels/tags.html' %}
{% include 'inc/panels/custom_fields.html' %}
{% plugin_right_page object %}
diff --git a/netbox/templates/ipam/asn.html b/netbox/templates/ipam/asn.html
index 26903b71c..a54a0aee5 100644
--- a/netbox/templates/ipam/asn.html
+++ b/netbox/templates/ipam/asn.html
@@ -39,54 +39,21 @@
Description |
{{ object.description|placeholder }} |
-
- Sites |
-
- {% if sites_count %}
- {{ sites_count }}
- {% else %}
- {{ ''|placeholder }}
- {% endif %}
- |
-
-
- Providers |
-
- {% if providers_count %}
- {{ providers_count }}
- {% else %}
- {{ ''|placeholder }}
- {% endif %}
- |
-
{% plugin_left_page object %}
+ {% include 'inc/panels/tags.html' %}
+ {% include 'inc/panels/related_objects.html' %}
{% include 'inc/panels/custom_fields.html' %}
- {% include 'inc/panels/tags.html' with tags=object.tags.all url='ipam:asn_list' %}
{% include 'inc/panels/comments.html' %}
{% plugin_right_page object %}
-
-
{% plugin_full_width_page object %}
diff --git a/netbox/templates/ipam/vrf.html b/netbox/templates/ipam/vrf.html
index b53862f9e..c365efae3 100644
--- a/netbox/templates/ipam/vrf.html
+++ b/netbox/templates/ipam/vrf.html
@@ -35,25 +35,14 @@
Description |
{{ object.description|placeholder }} |
-
- Prefixes |
-
- {{ prefix_count }}
- |
-
-
- IP Addresses |
-
- {{ ipaddress_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' %}
{% include 'inc/panels/comments.html' %}
{% plugin_right_page object %}
diff --git a/netbox/templates/virtualization/cluster.html b/netbox/templates/virtualization/cluster.html
index 5f34a82c5..3dfef108b 100644
--- a/netbox/templates/virtualization/cluster.html
+++ b/netbox/templates/virtualization/cluster.html
@@ -44,10 +44,6 @@
Site |
{{ object.site|linkify|placeholder }} |
-
- Virtual Machines |
- {{ object.virtual_machines.count }} |
-