Add GenericRelation to originating cable paths on PathEndpoint

This commit is contained in:
Jeremy Stretch 2020-10-01 11:30:03 -04:00
parent 46df5a97b2
commit 19a3a4d4ef
8 changed files with 50 additions and 87 deletions

View File

@ -252,15 +252,19 @@ class CableTermination(models.Model):
return endpoints return endpoints
class PathEndpoint: class PathEndpoint(models.Model):
"""
Any object which may serve as either endpoint of a CablePath.
"""
paths = GenericRelation(
to='dcim.CablePath',
content_type_field='origin_type',
object_id_field='origin_id',
related_query_name='%(class)s'
)
def get_connections(self): class Meta:
from dcim.models import CablePath abstract = True
return CablePath.objects.filter(
origin_type=ContentType.objects.get_for_model(self),
origin_id=self.pk,
destination_id__isnull=False
)
# #

View File

@ -32,7 +32,7 @@ from . import filters, forms, tables
from .choices import DeviceFaceChoices from .choices import DeviceFaceChoices
from .constants import NONCONNECTABLE_IFACE_TYPES from .constants import NONCONNECTABLE_IFACE_TYPES
from .models import ( from .models import (
Cable, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay, Cable, CablePath, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay,
DeviceBayTemplate, DeviceRole, DeviceType, FrontPort, FrontPortTemplate, Interface, InterfaceTemplate, DeviceBayTemplate, DeviceRole, DeviceType, FrontPort, FrontPortTemplate, Interface, InterfaceTemplate,
InventoryItem, Manufacturer, Platform, PowerFeed, PowerOutlet, PowerOutletTemplate, PowerPanel, PowerPort, InventoryItem, Manufacturer, Platform, PowerFeed, PowerOutlet, PowerOutletTemplate, PowerPanel, PowerPort,
PowerPortTemplate, Rack, RackGroup, RackReservation, RackRole, RearPort, RearPortTemplate, Region, Site, PowerPortTemplate, Rack, RackGroup, RackReservation, RackRole, RearPort, RearPortTemplate, Region, Site,
@ -1018,32 +1018,36 @@ class DeviceView(ObjectView):
# Console ports # Console ports
consoleports = ConsolePort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related( consoleports = ConsolePort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related(
'connected_endpoint__device', 'cable', Prefetch('paths', queryset=CablePath.objects.filter(destination_id__isnull=False)),
'cable',
) )
# Console server ports # Console server ports
consoleserverports = ConsoleServerPort.objects.restrict(request.user, 'view').filter( consoleserverports = ConsoleServerPort.objects.restrict(request.user, 'view').filter(
device=device device=device
).prefetch_related( ).prefetch_related(
'connected_endpoint__device', 'cable', Prefetch('paths', queryset=CablePath.objects.filter(destination_id__isnull=False)),
'cable',
) )
# Power ports # Power ports
powerports = PowerPort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related( powerports = PowerPort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related(
'_connected_poweroutlet__device', 'cable', Prefetch('paths', queryset=CablePath.objects.filter(destination_id__isnull=False)),
'cable',
) )
# Power outlets # Power outlets
poweroutlets = PowerOutlet.objects.restrict(request.user, 'view').filter(device=device).prefetch_related( poweroutlets = PowerOutlet.objects.restrict(request.user, 'view').filter(device=device).prefetch_related(
'connected_endpoint__device', 'cable', 'power_port', Prefetch('paths', queryset=CablePath.objects.filter(destination_id__isnull=False)),
'cable', 'power_port',
) )
# Interfaces # Interfaces
interfaces = device.vc_interfaces.restrict(request.user, 'view').prefetch_related( interfaces = device.vc_interfaces.restrict(request.user, 'view').prefetch_related(
Prefetch('paths', queryset=CablePath.objects.filter(destination_id__isnull=False)),
Prefetch('ip_addresses', queryset=IPAddress.objects.restrict(request.user)), Prefetch('ip_addresses', queryset=IPAddress.objects.restrict(request.user)),
Prefetch('member_interfaces', queryset=Interface.objects.restrict(request.user)), Prefetch('member_interfaces', queryset=Interface.objects.restrict(request.user)),
'lag', '_connected_interface__device', '_connected_circuittermination__circuit', 'cable', 'lag', 'cable', 'tags',
'cable__termination_a', 'cable__termination_b', 'tags'
) )
# Front ports # Front ports

View File

@ -36,18 +36,7 @@
</td> </td>
{# Connection #} {# Connection #}
{% if cp.connected_endpoint %} {% include 'dcim/inc/endpoint_connection.html' with paths=cp.paths.all %}
<td>
<a href="{% url 'dcim:device' pk=cp.connected_endpoint.device.pk %}">{{ cp.connected_endpoint.device }}</a>
</td>
<td>
{{ cp.connected_endpoint }}
</td>
{% else %}
<td colspan="2">
<span class="text-muted">Not connected</span>
</td>
{% endif %}
{# Actions #} {# Actions #}
<td class="text-right noprint"> <td class="text-right noprint">

View File

@ -38,18 +38,7 @@
</td> </td>
{# Connection #} {# Connection #}
{% if csp.connected_endpoint %} {% include 'dcim/inc/endpoint_connection.html' with paths=csp.paths.all %}
<td>
<a href="{% url 'dcim:device' pk=csp.connected_endpoint.device.pk %}">{{ csp.connected_endpoint.device }}</a>
</td>
<td>
{{ csp.connected_endpoint }}
</td>
{% else %}
<td colspan="2">
<span class="text-muted">Not connected</span>
</td>
{% endif %}
{# Actions #} {# Actions #}
<td class="text-right noprint"> <td class="text-right noprint">

View File

@ -0,0 +1,10 @@
{% if paths|length > 1 %}
<td colspan="2">Multiple connections</td>
{% elif paths %}
{% with endpoint=paths.0.destination %}
<td><a href="{{ endpoint.parent.get_absolute_url }}">{{ endpoint.parent }}</a></td>
<td><a href="{{ endpoint.get_absolute_url }}">{{ endpoint }}</a></td>
{% endwith %}
{% else %}
<td colspan="2" class="text-muted">Not connected</td>
{% endif %}

View File

@ -76,18 +76,7 @@
{% elif iface.is_wireless %} {% elif iface.is_wireless %}
<td colspan="2" class="text-muted">Wireless interface</td> <td colspan="2" class="text-muted">Wireless interface</td>
{% else %} {% else %}
{% with path_count=iface.get_connections.count %} {% include 'dcim/inc/endpoint_connection.html' with paths=iface.paths.all %}
{% if path_count > 1 %}
<td colspan="2">Multiple connections</td>
{% elif path_count %}
{% with endpoint=iface.get_connections.first.destination %}
<td><a href="{{ endpoint.parent.get_absolute_url }}">{{ endpoint.parent }}</a></td>
<td><a href="{{ endpoint.get_absolute_url }}">{{ endpoint }}</a></td>
{% endwith %}
{% else %}
<td colspan="2" class="text-muted">Not connected</td>
{% endif %}
{% endwith %}
{% endif %} {% endif %}
{# Buttons #} {# Buttons #}

View File

@ -49,27 +49,20 @@
</td> </td>
{# Connection #} {# Connection #}
{% if po.connected_endpoint %} {% with paths=po.paths.all %}
{% with pp=po.connected_endpoint %} {% include 'dcim/inc/endpoint_connection.html' %}
<td> <td>
<a href="{% url 'dcim:device' pk=pp.device.pk %}">{{ pp.device }}</a> {% if paths|length == 1 %}
</td> {% with pp=paths.0.destination %}
<td> {% if pp.allocated_draw %}
{{ pp }} {{ pp.allocated_draw }}W{% if pp.maximum_draw %} ({{ pp.maximum_draw }}W max){% endif %}
</td> {% elif pp.maximum_draw %}
<td> {{ pp.maximum_draw }}W
{% if pp.allocated_draw %} {% endif %}
{{ pp.allocated_draw }}W{% if pp.maximum_draw %} ({{ pp.maximum_draw }}W max){% endif %} {% endwith %}
{% elif pp.maximum_draw %} {% endif %}
{{ pp.maximum_draw }}W
{% endif %}
</td>
{% endwith %}
{% else %}
<td colspan="3">
<span class="text-muted">Not connected</span>
</td> </td>
{% endif %} {% endwith %}
{# Actions #} {# Actions #}
<td class="text-right noprint"> <td class="text-right noprint">

View File

@ -45,22 +45,7 @@
</td> </td>
{# Connection #} {# Connection #}
{% if pp.connected_endpoint.device %} {% include 'dcim/inc/endpoint_connection.html' with paths=pp.paths.all %}
<td>
<a href="{% url 'dcim:device' pk=pp.connected_endpoint.device.pk %}">{{ pp.connected_endpoint.device }}</a>
</td>
<td>
{{ pp.connected_endpoint }}
</td>
{% elif pp.connected_endpoint %}
<td colspan="2">
<a href="{{ pp.connected_endpoint.get_absolute_url }}">{{ pp.connected_endpoint }}</a>
</td>
{% else %}
<td colspan="2">
<span class="text-muted">Not connected</span>
</td>
{% endif %}
{# Actions #} {# Actions #}
<td class="text-right noprint"> <td class="text-right noprint">