1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Standard related object links across all models

This commit is contained in:
jeremystretch
2023-01-25 17:27:57 -05:00
committed by jeremystretch
parent 48e5b395b2
commit 8f7c100e22
16 changed files with 124 additions and 275 deletions

View File

@ -29,6 +29,15 @@ class ProviderListView(generic.ObjectListView):
class ProviderView(generic.ObjectView): class ProviderView(generic.ObjectView):
queryset = Provider.objects.all() 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') @register_model_view(Provider, 'edit')
class ProviderEditView(generic.ObjectEditView): class ProviderEditView(generic.ObjectEditView):
@ -79,6 +88,18 @@ class ProviderNetworkListView(generic.ObjectListView):
class ProviderNetworkView(generic.ObjectView): class ProviderNetworkView(generic.ObjectView):
queryset = ProviderNetwork.objects.all() 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') @register_model_view(ProviderNetwork, 'edit')
class ProviderNetworkEditView(generic.ObjectEditView): class ProviderNetworkEditView(generic.ObjectEditView):

View File

@ -21,9 +21,7 @@ from utilities.paginator import EnhancedPaginator, get_paginate_count
from utilities.permissions import get_permission_for_model from utilities.permissions import get_permission_for_model
from utilities.utils import count_related from utilities.utils import count_related
from utilities.views import GetReturnURLMixin, ObjectPermissionRequiredMixin, ViewTab, register_model_view from utilities.views import GetReturnURLMixin, ObjectPermissionRequiredMixin, ViewTab, register_model_view
from virtualization.filtersets import VirtualMachineFilterSet
from virtualization.models import VirtualMachine from virtualization.models import VirtualMachine
from virtualization.tables import VirtualMachineTable
from . import filtersets, forms, tables from . import filtersets, forms, tables
from .choices import DeviceFaceChoices from .choices import DeviceFaceChoices
from .constants import NONCONNECTABLE_IFACE_TYPES from .constants import NONCONNECTABLE_IFACE_TYPES
@ -359,24 +357,24 @@ class SiteView(generic.ObjectView):
queryset = Site.objects.prefetch_related('tenant__group') queryset = Site.objects.prefetch_related('tenant__group')
def get_extra_context(self, request, instance): def get_extra_context(self, request, instance):
related_models = [ related_models = (
# DCIM # DCIM
Location.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), (Rack.objects.restrict(request.user, 'view').filter(site=instance), 'site_id'),
Device.objects.restrict(request.user, 'view').filter(site=instance), (Device.objects.restrict(request.user, 'view').filter(site=instance), 'site_id'),
# Virtualization # Virtualization
VirtualMachine.objects.restrict(request.user, 'view').filter(cluster__site=instance), (VirtualMachine.objects.restrict(request.user, 'view').filter(cluster__site=instance), 'site_id'),
# IPAM # IPAM
Prefix.objects.restrict(request.user, 'view').filter(site=instance), (Prefix.objects.restrict(request.user, 'view').filter(site=instance), 'site_id'),
ASN.objects.restrict(request.user, 'view').filter(sites=instance), (ASN.objects.restrict(request.user, 'view').filter(sites=instance), 'site_id'),
VLANGroup.objects.restrict(request.user, 'view').filter( (VLANGroup.objects.restrict(request.user, 'view').filter(
scope_type=ContentType.objects.get_for_model(Site), scope_type=ContentType.objects.get_for_model(Site),
scope_id=instance.pk scope_id=instance.pk
), ), 'site_id'),
VLAN.objects.restrict(request.user, 'view').filter(site=instance), (VLAN.objects.restrict(request.user, 'view').filter(site=instance), 'site_id'),
# Circuits # 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( locations = Location.objects.add_related_count(
Location.objects.all(), Location.objects.all(),
@ -658,6 +656,11 @@ class RackView(generic.ObjectView):
queryset = Rack.objects.prefetch_related('site__region', 'tenant__group', 'location', 'role') queryset = Rack.objects.prefetch_related('site__region', 'tenant__group', 'location', 'role')
def get_extra_context(self, request, instance): 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 # Get 0U devices located within the rack
nonracked_devices = Device.objects.filter( nonracked_devices = Device.objects.filter(
rack=instance, rack=instance,
@ -675,11 +678,6 @@ class RackView(generic.ObjectView):
prev_rack = peer_racks.filter(_name__lt=instance._name).reverse().first() prev_rack = peer_racks.filter(_name__lt=instance._name).reverse().first()
reservations = RackReservation.objects.restrict(request.user, 'view').filter(rack=instance) 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 # Determine any additional parameters to pass when embedding the rack elevations
svg_extra = '&'.join([ svg_extra = '&'.join([
@ -687,9 +685,8 @@ class RackView(generic.ObjectView):
]) ])
return { return {
'device_count': device_count, 'related_models': related_models,
'reservations': reservations, 'reservations': reservations,
'power_feeds': power_feeds,
'nonracked_devices': nonracked_devices, 'nonracked_devices': nonracked_devices,
'next_rack': next_rack, 'next_rack': next_rack,
'prev_rack': prev_rack, 'prev_rack': prev_rack,
@ -881,10 +878,12 @@ class DeviceTypeView(generic.ObjectView):
queryset = DeviceType.objects.all() queryset = DeviceType.objects.all()
def get_extra_context(self, request, instance): 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 { return {
'instance_count': instance_count, 'related_models': related_models,
} }
@ -1119,10 +1118,12 @@ class ModuleTypeView(generic.ObjectView):
queryset = ModuleType.objects.all() queryset = ModuleType.objects.all()
def get_extra_context(self, request, instance): 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 { return {
'instance_count': instance_count, 'related_models': related_models,
} }
@ -1807,13 +1808,9 @@ class DeviceView(generic.ObjectView):
vc_members = [] vc_members = []
services = Service.objects.restrict(request.user, 'view').filter(device=instance) services = Service.objects.restrict(request.user, 'view').filter(device=instance)
vdcs = VirtualDeviceContext.objects.restrict(request.user, 'view').filter(device=instance).prefetch_related(
'tenant'
)
return { return {
'services': services, 'services': services,
'vdcs': vdcs,
'vc_members': vc_members, 'vc_members': vc_members,
'svg_extra': f'highlight=id:{instance.pk}' 'svg_extra': f'highlight=id:{instance.pk}'
} }
@ -2114,6 +2111,21 @@ class ModuleListView(generic.ObjectListView):
class ModuleView(generic.ObjectView): class ModuleView(generic.ObjectView):
queryset = Module.objects.all() 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') @register_model_view(Module, 'edit')
class ModuleEditView(generic.ObjectEditView): class ModuleEditView(generic.ObjectEditView):
@ -3436,6 +3448,15 @@ class PowerPanelListView(generic.ObjectListView):
class PowerPanelView(generic.ObjectView): class PowerPanelView(generic.ObjectView):
queryset = PowerPanel.objects.all() 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') @register_model_view(PowerPanel, 'edit')
class PowerPanelEditView(generic.ObjectEditView): class PowerPanelEditView(generic.ObjectEditView):
@ -3537,6 +3558,15 @@ class VirtualDeviceContextListView(generic.ObjectListView):
class VirtualDeviceContextView(generic.ObjectView): class VirtualDeviceContextView(generic.ObjectView):
queryset = VirtualDeviceContext.objects.all() 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') @register_model_view(VirtualDeviceContext, 'edit')
class VirtualDeviceContextEditView(generic.ObjectEditView): class VirtualDeviceContextEditView(generic.ObjectEditView):

View File

@ -37,8 +37,10 @@ class VRFView(generic.ObjectView):
queryset = VRF.objects.all() queryset = VRF.objects.all()
def get_extra_context(self, request, instance): def get_extra_context(self, request, instance):
prefix_count = Prefix.objects.restrict(request.user, 'view').filter(vrf=instance).count() related_models = (
ipaddress_count = IPAddress.objects.restrict(request.user, 'view').filter(vrf=instance).count() (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( import_targets_table = tables.RouteTargetTable(
instance.import_targets.all(), instance.import_targets.all(),
@ -50,8 +52,7 @@ class VRFView(generic.ObjectView):
) )
return { return {
'prefix_count': prefix_count, 'related_models': related_models,
'ipaddress_count': ipaddress_count,
'import_targets_table': import_targets_table, 'import_targets_table': import_targets_table,
'export_targets_table': export_targets_table, 'export_targets_table': export_targets_table,
} }
@ -228,12 +229,13 @@ class ASNView(generic.ObjectView):
queryset = ASN.objects.all() queryset = ASN.objects.all()
def get_extra_context(self, request, instance): def get_extra_context(self, request, instance):
sites = instance.sites.restrict(request.user, 'view') related_models = (
providers = instance.providers.restrict(request.user, 'view') (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 { return {
'sites_count': sites.count(), 'related_models': related_models,
'providers_count': providers.count(),
} }
@ -868,7 +870,6 @@ class VLANGroupView(generic.ObjectView):
Prefetch('prefixes', queryset=Prefix.objects.restrict(request.user)), Prefetch('prefixes', queryset=Prefix.objects.restrict(request.user)),
'tenant', 'site', 'role', 'tenant', 'site', 'role',
).order_by('vid') ).order_by('vid')
vlans_count = vlans.count()
vlans = add_available_vlans(vlans, vlan_group=instance) vlans = add_available_vlans(vlans, vlan_group=instance)
vlans_table = tables.VLANTable(vlans, user=request.user, exclude=('group',)) vlans_table = tables.VLANTable(vlans, user=request.user, exclude=('group',))

View File

@ -37,21 +37,16 @@
<th scope="row">Description</th> <th scope="row">Description</th>
<td>{{ object.description|placeholder }}</td> <td>{{ object.description|placeholder }}</td>
</tr> </tr>
<tr>
<th scope="row">Circuits</th>
<td>
<a href="{% url 'circuits:circuit_list' %}?provider={{ object.slug }}">{{ object.circuits.count }}</a>
</td>
</tr>
</table> </table>
</div> </div>
</div> </div>
{% include 'inc/panels/tags.html' %} {% include 'inc/panels/tags.html' %}
{% include 'inc/panels/comments.html' %}
{% plugin_left_page object %} {% plugin_left_page object %}
</div> </div>
<div class="col col-md-6"> <div class="col col-md-6">
{% include 'inc/panels/related_objects.html' %}
{% include 'inc/panels/custom_fields.html' %} {% include 'inc/panels/custom_fields.html' %}
{% include 'inc/panels/comments.html' %}
{% include 'inc/panels/contacts.html' %} {% include 'inc/panels/contacts.html' %}
{% plugin_right_page object %} {% plugin_right_page object %}
</div> </div>

View File

@ -37,12 +37,13 @@
</table> </table>
</div> </div>
</div> </div>
{% include 'inc/panels/tags.html' %}
{% plugin_left_page object %} {% plugin_left_page object %}
</div> </div>
<div class="col col-md-6"> <div class="col col-md-6">
{% include 'inc/panels/custom_fields.html' %} {% include 'inc/panels/related_objects.html' %}
{% include 'inc/panels/tags.html' %}
{% include 'inc/panels/comments.html' %} {% include 'inc/panels/comments.html' %}
{% include 'inc/panels/custom_fields.html' %}
{% plugin_right_page object %} {% plugin_right_page object %}
</div> </div>
</div> </div>

View File

@ -157,28 +157,10 @@
{% include 'inc/panels/comments.html' %} {% include 'inc/panels/comments.html' %}
<div class="card"> <div class="card">
<h5 class="card-header">Virtual Device Contexts</h5> <h5 class="card-header">Virtual Device Contexts</h5>
<div class="card-body"> <div class="card-body htmx-container table-responsive"
{% if vdcs %} hx-get="{% url 'dcim:virtualdevicecontext_list' %}?device_id={{ object.pk }}"
<table class="table table-hover"> hx-trigger="load"
<tr> ></div>
<th>Name</th>
<th>Status</th>
<th>Identifier</th>
<th>Tenant</th>
</tr>
{% for vdc in vdcs %}
<tr>
<td>{{ vdc|linkify }}</td>
<td>{% badge vdc.get_status_display bg_color=vdc.get_status_color %}</td>
<td>{{ vdc.identifier|placeholder }}</td>
<td>{{ vdc.tenant|linkify|placeholder }}</td>
</tr>
{% endfor %}
</table>
{% else %}
<div class="text-muted">None</div>
{% endif %}
</div>
{% if perms.dcim.add_virtualdevicecontext %} {% if perms.dcim.add_virtualdevicecontext %}
<div class="card-footer text-end noprint"> <div class="card-footer text-end noprint">
<a href="{% url 'dcim:virtualdevicecontext_add' %}?device={{ object.pk }}" class="btn btn-sm btn-primary"> <a href="{% url 'dcim:virtualdevicecontext_add' %}?device={{ object.pk }}" class="btn btn-sm btn-primary">

View File

@ -85,18 +85,15 @@
{% endif %} {% endif %}
</td> </td>
</tr> </tr>
<tr>
<td>Instances</td>
<td><a href="{% url 'dcim:device_list' %}?device_type_id={{ object.pk }}">{{ instance_count }}</a></td>
</tr>
</table> </table>
</div> </div>
</div> </div>
{% include 'inc/panels/tags.html' %}
{% plugin_left_page object %} {% plugin_left_page object %}
</div> </div>
<div class="col col-md-6"> <div class="col col-md-6">
{% include 'inc/panels/related_objects.html' %}
{% include 'inc/panels/custom_fields.html' %} {% include 'inc/panels/custom_fields.html' %}
{% include 'inc/panels/tags.html' %}
{% include 'inc/panels/comments.html' %} {% include 'inc/panels/comments.html' %}
{% plugin_right_page object %} {% plugin_right_page object %}
</div> </div>

View File

@ -81,103 +81,13 @@
</table> </table>
</div> </div>
</div> </div>
{% include 'inc/panels/custom_fields.html' %}
{% include 'inc/panels/tags.html' %} {% include 'inc/panels/tags.html' %}
{% include 'inc/panels/comments.html' %} {% include 'inc/panels/comments.html' %}
{% plugin_left_page object %} {% plugin_left_page object %}
</div> </div>
<div class="col col-md-6"> <div class="col col-md-6">
<div class="card"> {% include 'inc/panels/related_objects.html' %}
<h5 class="card-header">Components</h5> {% include 'inc/panels/custom_fields.html' %}
<div class="card-body">
<table class="table table-hover attr-table">
<tr>
<th scope="row">Interfaces</th>
<td>
{% with component_count=object.interfaces.count %}
{% if component_count %}
<a href="{% url 'dcim:interface_list' %}?module_id={{ object.pk }}">{{ component_count }}</a>
{% else %}
{{ ''|placeholder }}
{% endif %}
{% endwith %}
</td>
</tr>
<tr>
<th scope="row">Console Ports</th>
<td>
{% with component_count=object.consoleports.count %}
{% if component_count %}
<a href="{% url 'dcim:consoleport_list' %}?module_id={{ object.pk }}">{{ component_count }}</a>
{% else %}
{{ ''|placeholder }}
{% endif %}
{% endwith %}
</td>
</tr>
<tr>
<th scope="row">Console Server Ports</th>
<td>
{% with component_count=object.consoleserverports.count %}
{% if component_count %}
<a href="{% url 'dcim:consoleserverport_list' %}?module_id={{ object.pk }}">{{ component_count }}</a>
{% else %}
{{ ''|placeholder }}
{% endif %}
{% endwith %}
</td>
</tr>
<tr>
<th scope="row">Power Ports</th>
<td>
{% with component_count=object.powerports.count %}
{% if component_count %}
<a href="{% url 'dcim:powerport_list' %}?module_id={{ object.pk }}">{{ component_count }}</a>
{% else %}
{{ ''|placeholder }}
{% endif %}
{% endwith %}
</td>
</tr>
<tr>
<th scope="row">Power Outlets</th>
<td>
{% with component_count=object.poweroutlets.count %}
{% if component_count %}
<a href="{% url 'dcim:poweroutlet_list' %}?module_id={{ object.pk }}">{{ component_count }}</a>
{% else %}
{{ ''|placeholder }}
{% endif %}
{% endwith %}
</td>
</tr>
<tr>
<th scope="row">Front Ports</th>
<td>
{% with component_count=object.frontports.count %}
{% if component_count %}
<a href="{% url 'dcim:frontport_list' %}?module_id={{ object.pk }}">{{ component_count }}</a>
{% else %}
{{ ''|placeholder }}
{% endif %}
{% endwith %}
</td>
</tr>
<tr>
<th scope="row">Rear Ports</th>
<td>
{% with component_count=object.rearports.count %}
{% if component_count %}
<a href="{% url 'dcim:rearport_list' %}?module_id={{ object.pk }}">{{ component_count }}</a>
{% else %}
{{ ''|placeholder }}
{% endif %}
{% endwith %}
</td>
</tr>
</table>
</div>
</div>
{% plugin_right_page object %} {% plugin_right_page object %}
</div> </div>
</div> </div>

View File

@ -36,19 +36,16 @@
{% endif %} {% endif %}
</td> </td>
</tr> </tr>
<tr>
<td>Instances</td>
<td><a href="{% url 'dcim:module_list' %}?module_type_id={{ object.pk }}">{{ instance_count }}</a></td>
</tr>
</table> </table>
</div> </div>
</div> </div>
{% include 'inc/panels/custom_fields.html' %} {% include 'inc/panels/tags.html' %}
{% include 'inc/panels/comments.html' %}
{% plugin_left_page object %} {% plugin_left_page object %}
</div> </div>
<div class="col col-md-6"> <div class="col col-md-6">
{% include 'inc/panels/tags.html' %} {% include 'inc/panels/related_objects.html' %}
{% include 'inc/panels/comments.html' %} {% include 'inc/panels/custom_fields.html' %}
{% include 'inc/panels/image_attachments.html' %} {% include 'inc/panels/image_attachments.html' %}
{% plugin_right_page object %} {% plugin_right_page object %}
</div> </div>

View File

@ -38,6 +38,7 @@
{% plugin_left_page object %} {% plugin_left_page object %}
</div> </div>
<div class="col col-md-6"> <div class="col col-md-6">
{% include 'inc/panels/related_objects.html' %}
{% include 'inc/panels/custom_fields.html' %} {% include 'inc/panels/custom_fields.html' %}
{% include 'inc/panels/contacts.html' %} {% include 'inc/panels/contacts.html' %}
{% include 'inc/panels/image_attachments.html' %} {% include 'inc/panels/image_attachments.html' %}

View File

@ -90,12 +90,6 @@
<th scope="row">Asset Tag</th> <th scope="row">Asset Tag</th>
<td class="font-monospace">{{ object.asset_tag|placeholder }}</td> <td class="font-monospace">{{ object.asset_tag|placeholder }}</td>
</tr> </tr>
<tr>
<th scope="row">Devices</th>
<td>
<a href="{% url 'dcim:device_list' %}?rack_id={{ object.id }}">{{ device_count }}</a>
</td>
</tr>
<tr> <tr>
<th scope="row">Space Utilization</th> <th scope="row">Space Utilization</th>
<td>{% utilization_graph object.get_utilization %}</td> <td>{% utilization_graph object.get_utilization %}</td>
@ -192,40 +186,6 @@
{% include 'inc/panels/custom_fields.html' %} {% include 'inc/panels/custom_fields.html' %}
{% include 'inc/panels/tags.html' %} {% include 'inc/panels/tags.html' %}
{% include 'inc/panels/comments.html' %} {% include 'inc/panels/comments.html' %}
{% if power_feeds %}
<div class="card">
<h5 class="card-header">
Power Feeds
</h5>
<div class="card-body">
<table class="table">
<tr>
<th>Panel</th>
<th>Feed</th>
<th>Status</th>
<th>Type</th>
<th>Utilization</th>
</tr>
{% for powerfeed in power_feeds %}
<tr>
<td>{{ powerfeed.power_panel|linkify }}</td>
<td>{{ powerfeed|linkify }}</td>
<td>{% badge powerfeed.get_status_display bg_color=powerfeed.get_status_color %}</td>
<td>{% badge powerfeed.get_type_display bg_color=powerfeed.get_type_color %}</td>
{% with power_port=powerfeed.connected_endpoints.0 %}
{% if power_port %}
<td>{% utilization_graph power_port.get_power_draw.allocated|percentage:powerfeed.available_power %}</td>
{% else %}
<td class="text-muted">N/A</td>
{% endif %}
{% endwith %}
</tr>
{% endfor %}
</table>
</div>
</div>
{% endif %}
{% include 'inc/panels/image_attachments.html' %} {% include 'inc/panels/image_attachments.html' %}
<div class="card"> <div class="card">
<h5 class="card-header"> <h5 class="card-header">
@ -300,6 +260,7 @@
</div> </div>
</div> </div>
</div> </div>
{% include 'inc/panels/related_objects.html' %}
{% include 'dcim/inc/nonracked_devices.html' %} {% include 'dcim/inc/nonracked_devices.html' %}
{% include 'inc/panels/contacts.html' %} {% include 'inc/panels/contacts.html' %}
{% plugin_right_page object %} {% plugin_right_page object %}

View File

@ -59,10 +59,11 @@
</div> </div>
</div> </div>
{% plugin_left_page object %} {% plugin_left_page object %}
{% include 'inc/panels/tags.html' %}
</div> </div>
<div class="col col-md-6"> <div class="col col-md-6">
{% include 'inc/panels/related_objects.html' %}
{% include 'inc/panels/comments.html' %} {% include 'inc/panels/comments.html' %}
{% include 'inc/panels/tags.html' %}
{% include 'inc/panels/custom_fields.html' %} {% include 'inc/panels/custom_fields.html' %}
{% plugin_right_page object %} {% plugin_right_page object %}
</div> </div>

View File

@ -39,54 +39,21 @@
<td>Description</td> <td>Description</td>
<td>{{ object.description|placeholder }}</td> <td>{{ object.description|placeholder }}</td>
</tr> </tr>
<tr>
<td>Sites</td>
<td>
{% if sites_count %}
<a href="{% url 'dcim:site_list' %}?asn_id={{ object.pk }}">{{ sites_count }}</a>
{% else %}
{{ ''|placeholder }}
{% endif %}
</td>
</tr>
<tr>
<td>Providers</td>
<td>
{% if providers_count %}
<a href="{% url 'circuits:provider_list' %}?asn_id={{ object.pk }}">{{ providers_count }}</a>
{% else %}
{{ ''|placeholder }}
{% endif %}
</td>
</tr>
</table> </table>
</div> </div>
</div> </div>
{% plugin_left_page object %} {% plugin_left_page object %}
{% include 'inc/panels/tags.html' %}
</div> </div>
<div class="col col-md-6"> <div class="col col-md-6">
{% include 'inc/panels/related_objects.html' %}
{% include 'inc/panels/custom_fields.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' %} {% include 'inc/panels/comments.html' %}
{% plugin_right_page object %} {% plugin_right_page object %}
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col col-md-12"> <div class="col col-md-12">
<div class="card">
<h5 class="card-header">Sites</h5>
<div class="card-body htmx-container table-responsive"
hx-get="{% url 'dcim:site_list' %}?asn_id={{ object.pk }}"
hx-trigger="load"
></div>
</div>
<div class="card">
<h5 class="card-header">Providers</h5>
<div class="card-body htmx-container table-responsive"
hx-get="{% url 'circuits:provider_list' %}?asn_id={{ object.pk }}"
hx-trigger="load"
></div>
</div>
{% plugin_full_width_page object %} {% plugin_full_width_page object %}
</div> </div>
</div> </div>

View File

@ -35,25 +35,14 @@
<th scope="row">Description</th> <th scope="row">Description</th>
<td>{{ object.description|placeholder }}</td> <td>{{ object.description|placeholder }}</td>
</tr> </tr>
<tr>
<th scope="row">Prefixes</th>
<td>
<a href="{% url 'ipam:prefix_list' %}?vrf_id={{ object.pk }}">{{ prefix_count }}</a>
</td>
</tr>
<tr>
<th scope="row">IP Addresses</th>
<td>
<a href="{% url 'ipam:ipaddress_list' %}?vrf_id={{ object.pk }}">{{ ipaddress_count }}</a>
</td>
</tr>
</table> </table>
</div> </div>
</div> </div>
{% include 'inc/panels/tags.html' %}
{% plugin_left_page object %} {% plugin_left_page object %}
</div> </div>
<div class="col col-md-6"> <div class="col col-md-6">
{% include 'inc/panels/tags.html' %} {% include 'inc/panels/related_objects.html' %}
{% include 'inc/panels/custom_fields.html' %} {% include 'inc/panels/custom_fields.html' %}
{% include 'inc/panels/comments.html' %} {% include 'inc/panels/comments.html' %}
{% plugin_right_page object %} {% plugin_right_page object %}

View File

@ -44,10 +44,6 @@
<th scope="row">Site</th> <th scope="row">Site</th>
<td>{{ object.site|linkify|placeholder }}</td> <td>{{ object.site|linkify|placeholder }}</td>
</tr> </tr>
<tr>
<th scope="row">Virtual Machines</th>
<td><a href="{% url 'virtualization:virtualmachine_list' %}?cluster_id={{ object.pk }}">{{ object.virtual_machines.count }}</a></td>
</tr>
</table> </table>
</div> </div>
</div> </div>