Просмотр исходного кода

Merge pull request #21597 from netbox-community/21012-interface-vlans-list

Fixes #21012: Ensure all tagged VLANs assigned to an interface are listed under the interface detail UI view
bctiemann 1 день назад
Родитель
Сommit
1c527366c9
4 измененных файлов с 17 добавлено и 80 удалено
  1. 1 17
      netbox/dcim/views.py
  2. 1 44
      netbox/ipam/tables/vlans.py
  3. 9 1
      netbox/templates/dcim/interface.html
  4. 6 18
      netbox/virtualization/views.py

+ 1 - 17
netbox/dcim/views.py

@@ -16,7 +16,7 @@ from circuits.models import Circuit, CircuitTermination
 from extras.ui.panels import CustomFieldsPanel, ImageAttachmentsPanel, TagsPanel
 from extras.ui.panels import CustomFieldsPanel, ImageAttachmentsPanel, TagsPanel
 from extras.views import ObjectConfigContextView, ObjectRenderConfigView
 from extras.views import ObjectConfigContextView, ObjectRenderConfigView
 from ipam.models import ASN, VLAN, IPAddress, Prefix, VLANGroup
 from ipam.models import ASN, VLAN, IPAddress, Prefix, VLANGroup
-from ipam.tables import InterfaceVLANTable, VLANTranslationRuleTable
+from ipam.tables import VLANTranslationRuleTable
 from netbox.object_actions import *
 from netbox.object_actions import *
 from netbox.ui import actions, layout
 from netbox.ui import actions, layout
 from netbox.ui.panels import (
 from netbox.ui.panels import (
@@ -3230,21 +3230,6 @@ class InterfaceView(generic.ObjectView):
         )
         )
         lag_interfaces_table.configure(request)
         lag_interfaces_table.configure(request)
 
 
-        # Get assigned VLANs and annotate whether each is tagged or untagged
-        vlans = []
-        if instance.untagged_vlan is not None:
-            vlans.append(instance.untagged_vlan)
-            vlans[0].tagged = False
-        for vlan in instance.tagged_vlans.restrict(request.user).prefetch_related('site', 'group', 'tenant', 'role'):
-            vlan.tagged = True
-            vlans.append(vlan)
-        vlan_table = InterfaceVLANTable(
-            interface=instance,
-            data=vlans,
-            orderable=False
-        )
-        vlan_table.configure(request)
-
         # Get VLAN translation rules
         # Get VLAN translation rules
         vlan_translation_table = None
         vlan_translation_table = None
         if instance.vlan_translation_policy:
         if instance.vlan_translation_policy:
@@ -3260,7 +3245,6 @@ class InterfaceView(generic.ObjectView):
             'bridge_interfaces_table': bridge_interfaces_table,
             'bridge_interfaces_table': bridge_interfaces_table,
             'child_interfaces_table': child_interfaces_table,
             'child_interfaces_table': child_interfaces_table,
             'lag_interfaces_table': lag_interfaces_table,
             'lag_interfaces_table': lag_interfaces_table,
-            'vlan_table': vlan_table,
             'vlan_translation_table': vlan_translation_table,
             'vlan_translation_table': vlan_translation_table,
         }
         }
 
 

+ 1 - 44
netbox/ipam/tables/vlans.py

@@ -1,19 +1,17 @@
 import django_tables2 as tables
 import django_tables2 as tables
 from django.utils.safestring import mark_safe
 from django.utils.safestring import mark_safe
 from django.utils.translation import gettext_lazy as _
 from django.utils.translation import gettext_lazy as _
-from django_tables2.utils import Accessor
 
 
 from dcim.models import Interface
 from dcim.models import Interface
 from dcim.tables.template_code import INTERFACE_LINKTERMINATION, LINKTERMINATION
 from dcim.tables.template_code import INTERFACE_LINKTERMINATION, LINKTERMINATION
 from ipam.models import *
 from ipam.models import *
 from netbox.tables import NetBoxTable, OrganizationalModelTable, PrimaryModelTable, columns
 from netbox.tables import NetBoxTable, OrganizationalModelTable, PrimaryModelTable, columns
-from tenancy.tables import TenancyColumnsMixin, TenantColumn
+from tenancy.tables import TenancyColumnsMixin
 from virtualization.models import VMInterface
 from virtualization.models import VMInterface
 
 
 from .template_code import *
 from .template_code import *
 
 
 __all__ = (
 __all__ = (
-    'InterfaceVLANTable',
     'VLANDevicesTable',
     'VLANDevicesTable',
     'VLANGroupTable',
     'VLANGroupTable',
     'VLANMembersTable',
     'VLANMembersTable',
@@ -198,47 +196,6 @@ class VLANVirtualMachinesTable(VLANMembersTable):
         exclude = ('id', )
         exclude = ('id', )
 
 
 
 
-class InterfaceVLANTable(NetBoxTable):
-    """
-    List VLANs assigned to a specific Interface.
-    """
-    vid = tables.Column(
-        linkify=True,
-        verbose_name=_('VID')
-    )
-    tagged = columns.BooleanColumn(
-        verbose_name=_('Tagged'),
-        false_mark=None
-    )
-    site = tables.Column(
-        verbose_name=_('Site'),
-        linkify=True
-    )
-    group = tables.Column(
-        accessor=Accessor('group__name'),
-        verbose_name=_('Group')
-    )
-    tenant = TenantColumn(
-        verbose_name=_('Tenant'),
-    )
-    status = columns.ChoiceFieldColumn(
-        verbose_name=_('Status'),
-    )
-    role = tables.Column(
-        verbose_name=_('Role'),
-        linkify=True
-    )
-
-    class Meta(NetBoxTable.Meta):
-        model = VLAN
-        fields = ('vid', 'tagged', 'site', 'group', 'name', 'tenant', 'status', 'role', 'description')
-        exclude = ('id', )
-
-    def __init__(self, interface, *args, **kwargs):
-        self.interface = interface
-        super().__init__(*args, **kwargs)
-
-
 #
 #
 # VLAN Translation
 # VLAN Translation
 #
 #

+ 9 - 1
netbox/templates/dcim/interface.html

@@ -86,6 +86,11 @@
               <th scope="row">{% trans "Q-in-Q SVLAN" %}</th>
               <th scope="row">{% trans "Q-in-Q SVLAN" %}</th>
               <td>{{ object.qinq_svlan|linkify|placeholder }}</td>
               <td>{{ object.qinq_svlan|linkify|placeholder }}</td>
             </tr>
             </tr>
+          {% elif object.mode %}
+            <tr>
+              <th scope="row">{% trans "Untagged VLAN" %}</th>
+              <td>{{ object.untagged_vlan|linkify|placeholder }}</td>
+            </tr>
           {% endif %}
           {% endif %}
           <tr>
           <tr>
             <th scope="row">{% trans "Transmit power (dBm)" %}</th>
             <th scope="row">{% trans "Transmit power (dBm)" %}</th>
@@ -411,7 +416,10 @@
   </div>
   </div>
   <div class="row mb-3">
   <div class="row mb-3">
     <div class="col col-md-12">
     <div class="col col-md-12">
-      {% include 'inc/panel_table.html' with table=vlan_table heading="VLANs" %}
+      <div class="card">
+        <h2 class="card-header">{% trans "VLANs" %}</h2>
+        {% htmx_table 'ipam:vlan_list' interface_id=object.pk %}
+      </div>
     </div>
     </div>
   </div>
   </div>
   {% if object.is_lag %}
   {% if object.is_lag %}

+ 6 - 18
netbox/virtualization/views.py

@@ -13,7 +13,7 @@ from dcim.tables import DeviceTable
 from extras.ui.panels import CustomFieldsPanel, ImageAttachmentsPanel, TagsPanel
 from extras.ui.panels import CustomFieldsPanel, ImageAttachmentsPanel, TagsPanel
 from extras.views import ObjectConfigContextView, ObjectRenderConfigView
 from extras.views import ObjectConfigContextView, ObjectRenderConfigView
 from ipam.models import IPAddress, VLANGroup
 from ipam.models import IPAddress, VLANGroup
-from ipam.tables import InterfaceVLANTable, VLANTranslationRuleTable
+from ipam.tables import VLANTranslationRuleTable
 from ipam.ui.panels import FHRPGroupAssignmentsPanel
 from ipam.ui.panels import FHRPGroupAssignmentsPanel
 from netbox.object_actions import (
 from netbox.object_actions import (
     AddObject,
     AddObject,
@@ -594,7 +594,11 @@ class VMInterfaceView(generic.ObjectView):
                     ),
                     ),
                 ],
                 ],
             ),
             ),
-            ContextTablePanel('vlan_table', title=_('Assigned VLANs')),
+            ObjectsTablePanel(
+                model='ipam.VLAN',
+                title=_('Assigned VLANs'),
+                filters={'vminterface_id': lambda ctx: ctx['object'].pk},
+            ),
             ContextTablePanel('vlan_translation_table', title=_('VLAN Translation')),
             ContextTablePanel('vlan_translation_table', title=_('VLAN Translation')),
             ContextTablePanel('child_interfaces_table', title=_('Child Interfaces')),
             ContextTablePanel('child_interfaces_table', title=_('Child Interfaces')),
         ],
         ],
@@ -620,24 +624,8 @@ class VMInterfaceView(generic.ObjectView):
             )
             )
             vlan_translation_table.configure(request)
             vlan_translation_table.configure(request)
 
 
-        # Get assigned VLANs and annotate whether each is tagged or untagged
-        vlans = []
-        if instance.untagged_vlan is not None:
-            vlans.append(instance.untagged_vlan)
-            vlans[0].tagged = False
-        for vlan in instance.tagged_vlans.restrict(request.user).prefetch_related('site', 'group', 'tenant', 'role'):
-            vlan.tagged = True
-            vlans.append(vlan)
-        vlan_table = InterfaceVLANTable(
-            interface=instance,
-            data=vlans,
-            orderable=False
-        )
-        vlan_table.configure(request)
-
         return {
         return {
             'child_interfaces_table': child_interfaces_tables,
             'child_interfaces_table': child_interfaces_tables,
-            'vlan_table': vlan_table,
             'vlan_translation_table': vlan_translation_table,
             'vlan_translation_table': vlan_translation_table,
         }
         }