Repository: netbox-community/netbox

Issue:
Interface Connections/Power Connections/Console Connections Device B always "-"
### NetBox version

v3.3.0

### Python version

3.9

### Steps to Reproduce

go to https://demo.netbox.dev/dcim/interface-connections/ for example and see Device B columns.

### Expected Behavior

Should show Device B name and Interface name.

### Observed Behavior

Only shows "-"


Discussion:

Resolving patch:
diff --git a/netbox/dcim/tables/__init__.py b/netbox/dcim/tables/__init__.py
--- a/netbox/dcim/tables/__init__.py
+++ b/netbox/dcim/tables/__init__.py
@@ -1,109 +1,8 @@
-import django_tables2 as tables
-from django_tables2.utils import Accessor
-
-from netbox.tables import BaseTable, columns
-from dcim.models import ConsolePort, Interface, PowerPort
 from .cables import *
+from .connections import *
 from .devices import *
 from .devicetypes import *
 from .modules import *
 from .power import *
 from .racks import *
 from .sites import *
-
-
-#
-# Device connections
-#
-
-class ConsoleConnectionTable(BaseTable):
-    console_server = tables.Column(
-        accessor=Accessor('_path__destination__device'),
-        orderable=False,
-        linkify=True,
-        verbose_name='Console Server'
-    )
-    console_server_port = tables.Column(
-        accessor=Accessor('_path__destination'),
-        orderable=False,
-        linkify=True,
-        verbose_name='Port'
-    )
-    device = tables.Column(
-        linkify=True
-    )
-    name = tables.Column(
-        linkify=True,
-        verbose_name='Console Port'
-    )
-    reachable = columns.BooleanColumn(
-        accessor=Accessor('_path__is_active'),
-        verbose_name='Reachable'
-    )
-
-    class Meta(BaseTable.Meta):
-        model = ConsolePort
-        fields = ('device', 'name', 'console_server', 'console_server_port', 'reachable')
-
-
-class PowerConnectionTable(BaseTable):
-    pdu = tables.Column(
-        accessor=Accessor('_path__destination__device'),
-        orderable=False,
-        linkify=True,
-        verbose_name='PDU'
-    )
-    outlet = tables.Column(
-        accessor=Accessor('_path__destination'),
-        orderable=False,
-        linkify=True,
-        verbose_name='Outlet'
-    )
-    device = tables.Column(
-        linkify=True
-    )
-    name = tables.Column(
-        linkify=True,
-        verbose_name='Power Port'
-    )
-    reachable = columns.BooleanColumn(
-        accessor=Accessor('_path__is_active'),
-        verbose_name='Reachable'
-    )
-
-    class Meta(BaseTable.Meta):
-        model = PowerPort
-        fields = ('device', 'name', 'pdu', 'outlet', 'reachable')
-
-
-class InterfaceConnectionTable(BaseTable):
-    device_a = tables.Column(
-        accessor=Accessor('device'),
-        linkify=True,
-        verbose_name='Device A'
-    )
-    interface_a = tables.Column(
-        accessor=Accessor('name'),
-        linkify=True,
-        verbose_name='Interface A'
-    )
-    device_b = tables.Column(
-        accessor=Accessor('_path__destination__device'),
-        orderable=False,
-        linkify=True,
-        verbose_name='Device B'
-    )
-    interface_b = tables.Column(
-        accessor=Accessor('_path__destination'),
-        orderable=False,
-        linkify=True,
-        verbose_name='Interface B'
-    )
-    reachable = columns.BooleanColumn(
-        accessor=Accessor('_path__is_active'),
-        verbose_name='Reachable'
-    )
-
-    class Meta(BaseTable.Meta):
-        model = Interface
-        fields = ('device_a', 'interface_a', 'device_b', 'interface_b', 'reachable')
diff --git a/netbox/dcim/tables/connections.py b/netbox/dcim/tables/connections.py
new file mode 100644
--- /dev/null
+++ b/netbox/dcim/tables/connections.py
@@ -0,0 +1,71 @@
+import django_tables2 as tables
+from django_tables2.utils import Accessor
+
+from netbox.tables import BaseTable, columns
+from dcim.models import ConsolePort, Interface, PowerPort
+from .devices import PathEndpointTable
+
+__all__ = (
+    'ConsoleConnectionTable',
+    'InterfaceConnectionTable',
+    'PowerConnectionTable',
+)
+
+
+#
+# Device connections
+#
+
+class ConsoleConnectionTable(PathEndpointTable):
+    device = tables.Column(
+        linkify=True
+    )
+    name = tables.Column(
+        linkify=True,
+        verbose_name='Console Port'
+    )
+    reachable = columns.BooleanColumn(
+        accessor=Accessor('_path__is_active'),
+        verbose_name='Reachable'
+    )
+
+    class Meta(BaseTable.Meta):
+        model = ConsolePort
+        fields = ('device', 'name', 'connection', 'reachable')
+
+
+class PowerConnectionTable(PathEndpointTable):
+    device = tables.Column(
+        linkify=True
+    )
+    name = tables.Column(
+        linkify=True,
+        verbose_name='Power Port'
+    )
+    reachable = columns.BooleanColumn(
+        accessor=Accessor('_path__is_active'),
+        verbose_name='Reachable'
+    )
+
+    class Meta(BaseTable.Meta):
+        model = PowerPort
+        fields = ('device', 'name', 'connection', 'reachable')
+
+
+class InterfaceConnectionTable(PathEndpointTable):
+    device = tables.Column(
+        accessor=Accessor('device'),
+        linkify=True
+    )
+    interface = tables.Column(
+        accessor=Accessor('name'),
+        linkify=True
+    )
+    reachable = columns.BooleanColumn(
+        accessor=Accessor('_path__is_active'),
+        verbose_name='Reachable'
+    )
+
+    class Meta(BaseTable.Meta):
+        model = Interface
+        fields = ('device', 'interface', 'connection', 'reachable')
diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py
--- a/netbox/dcim/views.py
+++ b/netbox/dcim/views.py
@@ -2893,7 +2893,7 @@ class CableBulkDeleteView(generic.BulkDeleteView):
 #
 
 class ConsoleConnectionsListView(generic.ObjectListView):
-    queryset = ConsolePort.objects.filter(_path__isnull=False).order_by('device')
+    queryset = ConsolePort.objects.filter(_path__is_complete=True)
     filterset = filtersets.ConsoleConnectionFilterSet
     filterset_form = forms.ConsoleConnectionFilterForm
     table = tables.ConsoleConnectionTable
@@ -2907,7 +2907,7 @@ def get_extra_context(self, request):
 
 
 class PowerConnectionsListView(generic.ObjectListView):
-    queryset = PowerPort.objects.filter(_path__isnull=False).order_by('device')
+    queryset = PowerPort.objects.filter(_path__is_complete=True)
     filterset = filtersets.PowerConnectionFilterSet
     filterset_form = forms.PowerConnectionFilterForm
     table = tables.PowerConnectionTable
@@ -2921,7 +2921,7 @@ def get_extra_context(self, request):
 
 
 class InterfaceConnectionsListView(generic.ObjectListView):
-    queryset = Interface.objects.filter(_path__isnull=False).order_by('device')
+    queryset = Interface.objects.filter(_path__is_complete=True)
     filterset = filtersets.InterfaceConnectionFilterSet
     filterset_form = forms.InterfaceConnectionFilterForm
     table = tables.InterfaceConnectionTable


Test patch: