From 59082d03644979ed502c1ed62155e808d0f41e4d Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 22 Oct 2025 13:43:13 -0400 Subject: [PATCH] Introduce base table classes with an 'owner' column for primary, organizational, and nested group models --- netbox/circuits/tables/circuits.py | 21 ++---- netbox/circuits/tables/providers.py | 27 +++---- netbox/circuits/tables/virtual_circuits.py | 13 ++-- netbox/core/tables/data.py | 6 +- netbox/dcim/tables/cables.py | 11 ++- netbox/dcim/tables/devices.py | 53 ++++--------- netbox/dcim/tables/devicetypes.py | 13 ++-- netbox/dcim/tables/modules.py | 25 ++----- netbox/dcim/tables/power.py | 21 ++---- netbox/dcim/tables/racks.py | 45 +++-------- netbox/dcim/tables/sites.py | 75 +++---------------- netbox/extras/tables/tables.py | 46 +++++++++++- netbox/ipam/tables/asn.py | 13 ++-- netbox/ipam/tables/fhrp.py | 11 +-- netbox/ipam/tables/ip.py | 40 ++++------ netbox/ipam/tables/services.py | 18 ++--- netbox/ipam/tables/vlans.py | 17 ++--- netbox/ipam/tables/vrfs.py | 18 ++--- netbox/netbox/tables/tables.py | 38 ++++++++++ netbox/netbox/tests/test_base_classes.py | 50 +++++++++++++ netbox/tenancy/tables/contacts.py | 30 ++------ netbox/tenancy/tables/tenants.py | 28 ++----- netbox/users/tables.py | 2 +- netbox/virtualization/tables/clusters.py | 21 +++--- .../virtualization/tables/virtualmachines.py | 9 +-- netbox/vpn/tables/crypto.py | 37 +++------ netbox/vpn/tables/l2vpn.py | 9 +-- netbox/vpn/tables/tunnels.py | 13 ++-- netbox/wireless/tables/wirelesslan.py | 26 ++----- netbox/wireless/tables/wirelesslink.py | 8 +- 30 files changed, 316 insertions(+), 428 deletions(-) diff --git a/netbox/circuits/tables/circuits.py b/netbox/circuits/tables/circuits.py index 901893a77..1c0e79d19 100644 --- a/netbox/circuits/tables/circuits.py +++ b/netbox/circuits/tables/circuits.py @@ -1,11 +1,9 @@ -from django.utils.translation import gettext_lazy as _ import django_tables2 as tables +from django.utils.translation import gettext_lazy as _ from circuits.models import * +from netbox.tables import NetBoxTable, OrganizationalModelTable, PrimaryModelTable, columns from tenancy.tables import ContactsColumnMixin, TenancyColumnsMixin - -from netbox.tables import NetBoxTable, columns - from .columns import CommitRateColumn __all__ = ( @@ -24,7 +22,7 @@ CIRCUITTERMINATION_LINK = """ """ -class CircuitTypeTable(NetBoxTable): +class CircuitTypeTable(OrganizationalModelTable): name = tables.Column( linkify=True, verbose_name=_('Name'), @@ -39,7 +37,7 @@ class CircuitTypeTable(NetBoxTable): verbose_name=_('Circuits') ) - class Meta(NetBoxTable.Meta): + class Meta(OrganizationalModelTable.Meta): model = CircuitType fields = ( 'pk', 'id', 'name', 'circuit_count', 'color', 'description', 'slug', 'tags', 'created', 'last_updated', @@ -48,7 +46,7 @@ class CircuitTypeTable(NetBoxTable): default_columns = ('pk', 'name', 'circuit_count', 'color', 'description') -class CircuitTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable): +class CircuitTable(TenancyColumnsMixin, ContactsColumnMixin, PrimaryModelTable): cid = tables.Column( linkify=True, verbose_name=_('Circuit ID') @@ -79,9 +77,6 @@ class CircuitTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable): verbose_name=_('Commit Rate') ) distance = columns.DistanceColumn() - comments = columns.MarkdownColumn( - verbose_name=_('Comments') - ) tags = columns.TagColumn( url_name='circuits:circuit_list' ) @@ -90,7 +85,7 @@ class CircuitTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable): linkify_item=True ) - class Meta(NetBoxTable.Meta): + class Meta(PrimaryModelTable.Meta): model = Circuit fields = ( 'pk', 'id', 'cid', 'provider', 'provider_account', 'type', 'status', 'tenant', 'tenant_group', @@ -163,7 +158,7 @@ class CircuitTerminationTable(NetBoxTable): ) -class CircuitGroupTable(NetBoxTable): +class CircuitGroupTable(OrganizationalModelTable): name = tables.Column( verbose_name=_('Name'), linkify=True @@ -177,7 +172,7 @@ class CircuitGroupTable(NetBoxTable): url_name='circuits:circuitgroup_list' ) - class Meta(NetBoxTable.Meta): + class Meta(OrganizationalModelTable.Meta): model = CircuitGroup fields = ( 'pk', 'name', 'description', 'circuit_group_assignment_count', 'tags', diff --git a/netbox/circuits/tables/providers.py b/netbox/circuits/tables/providers.py index 54a5c2cc9..4fbdff8c7 100644 --- a/netbox/circuits/tables/providers.py +++ b/netbox/circuits/tables/providers.py @@ -1,10 +1,10 @@ import django_tables2 as tables from django.utils.translation import gettext_lazy as _ -from circuits.models import * from django_tables2.utils import Accessor -from tenancy.tables import ContactsColumnMixin -from netbox.tables import NetBoxTable, columns +from circuits.models import * +from netbox.tables import PrimaryModelTable, columns +from tenancy.tables import ContactsColumnMixin __all__ = ( 'ProviderTable', @@ -13,7 +13,7 @@ __all__ = ( ) -class ProviderTable(ContactsColumnMixin, NetBoxTable): +class ProviderTable(ContactsColumnMixin, PrimaryModelTable): name = tables.Column( verbose_name=_('Name'), linkify=True @@ -42,14 +42,11 @@ class ProviderTable(ContactsColumnMixin, NetBoxTable): url_params={'provider_id': 'pk'}, verbose_name=_('Circuits') ) - comments = columns.MarkdownColumn( - verbose_name=_('Comments'), - ) tags = columns.TagColumn( url_name='circuits:provider_list' ) - class Meta(NetBoxTable.Meta): + class Meta(PrimaryModelTable.Meta): model = Provider fields = ( 'pk', 'id', 'name', 'accounts', 'account_count', 'asns', 'asn_count', 'circuit_count', 'description', @@ -58,7 +55,7 @@ class ProviderTable(ContactsColumnMixin, NetBoxTable): default_columns = ('pk', 'name', 'account_count', 'circuit_count') -class ProviderAccountTable(ContactsColumnMixin, NetBoxTable): +class ProviderAccountTable(ContactsColumnMixin, PrimaryModelTable): account = tables.Column( linkify=True, verbose_name=_('Account'), @@ -76,14 +73,11 @@ class ProviderAccountTable(ContactsColumnMixin, NetBoxTable): url_params={'provider_account_id': 'pk'}, verbose_name=_('Circuits') ) - comments = columns.MarkdownColumn( - verbose_name=_('Comments'), - ) tags = columns.TagColumn( url_name='circuits:provideraccount_list' ) - class Meta(NetBoxTable.Meta): + class Meta(PrimaryModelTable.Meta): model = ProviderAccount fields = ( 'pk', 'id', 'account', 'name', 'provider', 'circuit_count', 'comments', 'contacts', 'tags', 'created', @@ -92,7 +86,7 @@ class ProviderAccountTable(ContactsColumnMixin, NetBoxTable): default_columns = ('pk', 'account', 'name', 'provider', 'circuit_count') -class ProviderNetworkTable(NetBoxTable): +class ProviderNetworkTable(PrimaryModelTable): name = tables.Column( verbose_name=_('Name'), linkify=True @@ -101,14 +95,11 @@ class ProviderNetworkTable(NetBoxTable): verbose_name=_('Provider'), linkify=True ) - comments = columns.MarkdownColumn( - verbose_name=_('Comments'), - ) tags = columns.TagColumn( url_name='circuits:providernetwork_list' ) - class Meta(NetBoxTable.Meta): + class Meta(PrimaryModelTable.Meta): model = ProviderNetwork fields = ( 'pk', 'id', 'name', 'provider', 'service_id', 'description', 'comments', 'created', 'last_updated', 'tags', diff --git a/netbox/circuits/tables/virtual_circuits.py b/netbox/circuits/tables/virtual_circuits.py index ea3b6dc13..c55dfd178 100644 --- a/netbox/circuits/tables/virtual_circuits.py +++ b/netbox/circuits/tables/virtual_circuits.py @@ -2,7 +2,7 @@ import django_tables2 as tables from django.utils.translation import gettext_lazy as _ from circuits.models import * -from netbox.tables import NetBoxTable, columns +from netbox.tables import NetBoxTable, OrganizationalModelTable, PrimaryModelTable, columns from tenancy.tables import ContactsColumnMixin, TenancyColumnsMixin __all__ = ( @@ -12,7 +12,7 @@ __all__ = ( ) -class VirtualCircuitTypeTable(NetBoxTable): +class VirtualCircuitTypeTable(OrganizationalModelTable): name = tables.Column( linkify=True, verbose_name=_('Name'), @@ -27,7 +27,7 @@ class VirtualCircuitTypeTable(NetBoxTable): verbose_name=_('Circuits') ) - class Meta(NetBoxTable.Meta): + class Meta(OrganizationalModelTable.Meta): model = VirtualCircuitType fields = ( 'pk', 'id', 'name', 'virtual_circuit_count', 'color', 'description', 'slug', 'tags', 'created', @@ -36,7 +36,7 @@ class VirtualCircuitTypeTable(NetBoxTable): default_columns = ('pk', 'name', 'virtual_circuit_count', 'color', 'description') -class VirtualCircuitTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable): +class VirtualCircuitTable(TenancyColumnsMixin, ContactsColumnMixin, PrimaryModelTable): cid = tables.Column( linkify=True, verbose_name=_('Circuit ID') @@ -63,14 +63,11 @@ class VirtualCircuitTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable) url_params={'virtual_circuit_id': 'pk'}, verbose_name=_('Terminations') ) - comments = columns.MarkdownColumn( - verbose_name=_('Comments') - ) tags = columns.TagColumn( url_name='circuits:virtualcircuit_list' ) - class Meta(NetBoxTable.Meta): + class Meta(PrimaryModelTable.Meta): model = VirtualCircuit fields = ( 'pk', 'id', 'cid', 'provider', 'provider_account', 'provider_network', 'type', 'status', 'tenant', diff --git a/netbox/core/tables/data.py b/netbox/core/tables/data.py index 226a48081..db688b22a 100644 --- a/netbox/core/tables/data.py +++ b/netbox/core/tables/data.py @@ -2,7 +2,7 @@ from django.utils.translation import gettext_lazy as _ import django_tables2 as tables from core.models import * -from netbox.tables import NetBoxTable, columns +from netbox.tables import NetBoxTable, PrimaryModelTable, columns from .columns import BackendTypeColumn from .template_code import DATA_SOURCE_SYNC_BUTTON @@ -12,7 +12,7 @@ __all__ = ( ) -class DataSourceTable(NetBoxTable): +class DataSourceTable(PrimaryModelTable): name = tables.Column( verbose_name=_('Name'), linkify=True, @@ -42,7 +42,7 @@ class DataSourceTable(NetBoxTable): extra_buttons=DATA_SOURCE_SYNC_BUTTON, ) - class Meta(NetBoxTable.Meta): + class Meta(PrimaryModelTable.Meta): model = DataSource fields = ( 'pk', 'id', 'name', 'type', 'status', 'enabled', 'source_url', 'description', 'sync_interval', 'comments', diff --git a/netbox/dcim/tables/cables.py b/netbox/dcim/tables/cables.py index 321eb79f5..a4e3be269 100644 --- a/netbox/dcim/tables/cables.py +++ b/netbox/dcim/tables/cables.py @@ -1,11 +1,11 @@ -from django.utils.translation import gettext_lazy as _ import django_tables2 as tables -from django_tables2.utils import Accessor from django.utils.html import escape from django.utils.safestring import mark_safe +from django.utils.translation import gettext_lazy as _ +from django_tables2.utils import Accessor from dcim.models import Cable -from netbox.tables import NetBoxTable, columns +from netbox.tables import PrimaryModelTable, columns from tenancy.tables import TenancyColumnsMixin from .template_code import CABLE_LENGTH @@ -48,7 +48,7 @@ class CableTerminationsColumn(tables.Column): # Cables # -class CableTable(TenancyColumnsMixin, NetBoxTable): +class CableTable(TenancyColumnsMixin, PrimaryModelTable): a_terminations = CableTerminationsColumn( cable_end='A', orderable=False, @@ -117,12 +117,11 @@ class CableTable(TenancyColumnsMixin, NetBoxTable): verbose_name=_('Color Name'), orderable=False ) - comments = columns.MarkdownColumn() tags = columns.TagColumn( url_name='dcim:cable_list' ) - class Meta(NetBoxTable.Meta): + class Meta(PrimaryModelTable.Meta): model = Cable fields = ( 'pk', 'id', 'label', 'a_terminations', 'b_terminations', 'device_a', 'device_b', 'rack_a', 'rack_b', diff --git a/netbox/dcim/tables/devices.py b/netbox/dcim/tables/devices.py index dbdfae11d..e70738f02 100644 --- a/netbox/dcim/tables/devices.py +++ b/netbox/dcim/tables/devices.py @@ -3,7 +3,7 @@ from django.utils.translation import gettext_lazy as _ from django_tables2.utils import Accessor from dcim import models -from netbox.tables import NetBoxTable, columns +from netbox.tables import NestedGroupModelTable, NetBoxTable, OrganizationalModelTable, PrimaryModelTable, columns from tenancy.tables import ContactsColumnMixin, TenancyColumnsMixin from .template_code import * @@ -58,15 +58,7 @@ MACADDRESS_COPY_BUTTON = """ # Device roles # -class DeviceRoleTable(NetBoxTable): - name = columns.MPTTColumn( - verbose_name=_('Name'), - linkify=True - ) - parent = tables.Column( - verbose_name=_('Parent'), - linkify=True, - ) +class DeviceRoleTable(NestedGroupModelTable): device_count = columns.LinkedCountColumn( viewname='dcim:device_list', url_params={'role_id': 'pk'}, @@ -89,7 +81,7 @@ class DeviceRoleTable(NetBoxTable): url_name='dcim:devicerole_list' ) - class Meta(NetBoxTable.Meta): + class Meta(NestedGroupModelTable.Meta): model = models.DeviceRole fields = ( 'pk', 'id', 'name', 'parent', 'device_count', 'vm_count', 'color', 'vm_role', 'config_template', @@ -102,15 +94,7 @@ class DeviceRoleTable(NetBoxTable): # Platforms # -class PlatformTable(NetBoxTable): - name = columns.MPTTColumn( - verbose_name=_('Name'), - linkify=True - ) - parent = tables.Column( - verbose_name=_('Parent'), - linkify=True, - ) +class PlatformTable(NestedGroupModelTable): manufacturer = tables.Column( verbose_name=_('Manufacturer'), linkify=True @@ -133,7 +117,7 @@ class PlatformTable(NetBoxTable): url_name='dcim:platform_list' ) - class Meta(NetBoxTable.Meta): + class Meta(NestedGroupModelTable.Meta): model = models.Platform fields = ( 'pk', 'id', 'name', 'parent', 'manufacturer', 'device_count', 'vm_count', 'slug', 'config_template', @@ -148,7 +132,7 @@ class PlatformTable(NetBoxTable): # Devices # -class DeviceTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable): +class DeviceTable(TenancyColumnsMixin, ContactsColumnMixin, PrimaryModelTable): name = tables.TemplateColumn( verbose_name=_('Name'), template_code=DEVICE_LINK, @@ -249,7 +233,6 @@ class DeviceTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable): accessor='parent_bay', linkify=True ) - comments = columns.MarkdownColumn() tags = columns.TagColumn( url_name='dcim:device_list' ) @@ -284,7 +267,7 @@ class DeviceTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable): verbose_name=_('Inventory items') ) - class Meta(NetBoxTable.Meta): + class Meta(PrimaryModelTable.Meta): model = models.Device fields = ( 'pk', 'id', 'name', 'status', 'tenant', 'tenant_group', 'role', 'manufacturer', 'device_type', @@ -1050,7 +1033,7 @@ class DeviceInventoryItemTable(InventoryItemTable): ) -class InventoryItemRoleTable(NetBoxTable): +class InventoryItemRoleTable(OrganizationalModelTable): name = tables.Column( verbose_name=_('Name'), linkify=True @@ -1067,7 +1050,7 @@ class InventoryItemRoleTable(NetBoxTable): url_name='dcim:inventoryitemrole_list' ) - class Meta(NetBoxTable.Meta): + class Meta(OrganizationalModelTable.Meta): model = models.InventoryItemRole fields = ( 'pk', 'id', 'name', 'inventoryitem_count', 'color', 'description', 'slug', 'tags', 'actions', @@ -1079,7 +1062,7 @@ class InventoryItemRoleTable(NetBoxTable): # Virtual chassis # -class VirtualChassisTable(NetBoxTable): +class VirtualChassisTable(PrimaryModelTable): name = tables.Column( verbose_name=_('Name'), linkify=True @@ -1093,14 +1076,11 @@ class VirtualChassisTable(NetBoxTable): url_params={'virtual_chassis_id': 'pk'}, verbose_name=_('Members') ) - comments = columns.MarkdownColumn( - verbose_name=_('Comments'), - ) tags = columns.TagColumn( url_name='dcim:virtualchassis_list' ) - class Meta(NetBoxTable.Meta): + class Meta(PrimaryModelTable.Meta): model = models.VirtualChassis fields = ( 'pk', 'id', 'name', 'domain', 'master', 'member_count', 'description', 'comments', 'tags', 'created', @@ -1109,7 +1089,7 @@ class VirtualChassisTable(NetBoxTable): default_columns = ('pk', 'name', 'domain', 'master', 'member_count') -class VirtualDeviceContextTable(TenancyColumnsMixin, NetBoxTable): +class VirtualDeviceContextTable(TenancyColumnsMixin, PrimaryModelTable): name = tables.Column( verbose_name=_('Name'), linkify=True @@ -1140,14 +1120,11 @@ class VirtualDeviceContextTable(TenancyColumnsMixin, NetBoxTable): url_params={'vdc_id': 'pk'}, verbose_name=_('Interfaces') ) - - comments = columns.MarkdownColumn() - tags = columns.TagColumn( url_name='dcim:virtualdevicecontext_list' ) - class Meta(NetBoxTable.Meta): + class Meta(PrimaryModelTable.Meta): model = models.VirtualDeviceContext fields = ( 'pk', 'id', 'name', 'status', 'identifier', 'tenant', 'tenant_group', 'primary_ip', 'primary_ip4', @@ -1158,7 +1135,7 @@ class VirtualDeviceContextTable(TenancyColumnsMixin, NetBoxTable): ) -class MACAddressTable(NetBoxTable): +class MACAddressTable(PrimaryModelTable): mac_address = tables.TemplateColumn( template_code=MACADDRESS_LINK, verbose_name=_('MAC Address') @@ -1181,7 +1158,7 @@ class MACAddressTable(NetBoxTable): extra_buttons=MACADDRESS_COPY_BUTTON ) - class Meta(DeviceComponentTable.Meta): + class Meta(PrimaryModelTable.Meta): model = models.MACAddress fields = ( 'pk', 'id', 'mac_address', 'assigned_object_parent', 'assigned_object', 'description', 'comments', 'tags', diff --git a/netbox/dcim/tables/devicetypes.py b/netbox/dcim/tables/devicetypes.py index 91f9f3b47..843211a6d 100644 --- a/netbox/dcim/tables/devicetypes.py +++ b/netbox/dcim/tables/devicetypes.py @@ -2,7 +2,7 @@ import django_tables2 as tables from django.utils.translation import gettext_lazy as _ from dcim import models -from netbox.tables import NetBoxTable, columns +from netbox.tables import NetBoxTable, OrganizationalModelTable, PrimaryModelTable, columns from tenancy.tables import ContactsColumnMixin from .template_code import MODULAR_COMPONENT_TEMPLATE_BUTTONS, WEIGHT @@ -26,7 +26,7 @@ __all__ = ( # Manufacturers # -class ManufacturerTable(ContactsColumnMixin, NetBoxTable): +class ManufacturerTable(ContactsColumnMixin, OrganizationalModelTable): name = tables.Column( verbose_name=_('Name'), linkify=True @@ -60,7 +60,7 @@ class ManufacturerTable(ContactsColumnMixin, NetBoxTable): url_name='dcim:manufacturer_list' ) - class Meta(NetBoxTable.Meta): + class Meta(OrganizationalModelTable.Meta): model = models.Manufacturer fields = ( 'pk', 'id', 'name', 'racktype_count', 'devicetype_count', 'moduletype_count', 'inventoryitem_count', @@ -76,7 +76,7 @@ class ManufacturerTable(ContactsColumnMixin, NetBoxTable): # Device types # -class DeviceTypeTable(NetBoxTable): +class DeviceTypeTable(PrimaryModelTable): model = tables.Column( linkify=True, verbose_name=_('Device Type') @@ -93,9 +93,6 @@ class DeviceTypeTable(NetBoxTable): verbose_name=_('Full Depth'), false_mark=None ) - comments = columns.MarkdownColumn( - verbose_name=_('Comments'), - ) tags = columns.TagColumn( url_name='dcim:devicetype_list' ) @@ -148,7 +145,7 @@ class DeviceTypeTable(NetBoxTable): verbose_name=_('Inventory Items') ) - class Meta(NetBoxTable.Meta): + class Meta(PrimaryModelTable.Meta): model = models.DeviceType fields = ( 'pk', 'id', 'model', 'manufacturer', 'default_platform', 'slug', 'part_number', 'u_height', diff --git a/netbox/dcim/tables/modules.py b/netbox/dcim/tables/modules.py index 52edea8b4..78abfdd19 100644 --- a/netbox/dcim/tables/modules.py +++ b/netbox/dcim/tables/modules.py @@ -1,8 +1,8 @@ -from django.utils.translation import gettext_lazy as _ import django_tables2 as tables +from django.utils.translation import gettext_lazy as _ from dcim.models import Module, ModuleType, ModuleTypeProfile -from netbox.tables import NetBoxTable, columns +from netbox.tables import PrimaryModelTable, columns from .template_code import MODULETYPEPROFILE_ATTRIBUTES, WEIGHT __all__ = ( @@ -12,7 +12,7 @@ __all__ = ( ) -class ModuleTypeProfileTable(NetBoxTable): +class ModuleTypeProfileTable(PrimaryModelTable): name = tables.Column( verbose_name=_('Name'), linkify=True @@ -23,14 +23,11 @@ class ModuleTypeProfileTable(NetBoxTable): orderable=False, verbose_name=_('Attributes') ) - comments = columns.MarkdownColumn( - verbose_name=_('Comments'), - ) tags = columns.TagColumn( url_name='dcim:moduletypeprofile_list' ) - class Meta(NetBoxTable.Meta): + class Meta(PrimaryModelTable.Meta): model = ModuleTypeProfile fields = ( 'pk', 'id', 'name', 'description', 'comments', 'tags', 'created', 'last_updated', @@ -40,7 +37,7 @@ class ModuleTypeProfileTable(NetBoxTable): ) -class ModuleTypeTable(NetBoxTable): +class ModuleTypeTable(PrimaryModelTable): profile = tables.Column( verbose_name=_('Profile'), linkify=True @@ -64,14 +61,11 @@ class ModuleTypeTable(NetBoxTable): url_params={'module_type_id': 'pk'}, verbose_name=_('Instances') ) - comments = columns.MarkdownColumn( - verbose_name=_('Comments'), - ) tags = columns.TagColumn( url_name='dcim:moduletype_list' ) - class Meta(NetBoxTable.Meta): + class Meta(PrimaryModelTable.Meta): model = ModuleType fields = ( 'pk', 'id', 'model', 'profile', 'manufacturer', 'part_number', 'airflow', 'weight', 'description', @@ -82,7 +76,7 @@ class ModuleTypeTable(NetBoxTable): ) -class ModuleTable(NetBoxTable): +class ModuleTable(PrimaryModelTable): device = tables.Column( verbose_name=_('Device'), linkify=True @@ -103,14 +97,11 @@ class ModuleTable(NetBoxTable): status = columns.ChoiceFieldColumn( verbose_name=_('Status'), ) - comments = columns.MarkdownColumn( - verbose_name=_('Comments'), - ) tags = columns.TagColumn( url_name='dcim:module_list' ) - class Meta(NetBoxTable.Meta): + class Meta(PrimaryModelTable.Meta): model = Module fields = ( 'pk', 'id', 'device', 'module_bay', 'manufacturer', 'module_type', 'status', 'serial', 'asset_tag', diff --git a/netbox/dcim/tables/power.py b/netbox/dcim/tables/power.py index 40a58ad81..d7d62ea17 100644 --- a/netbox/dcim/tables/power.py +++ b/netbox/dcim/tables/power.py @@ -1,10 +1,9 @@ -from django.utils.translation import gettext_lazy as _ import django_tables2 as tables +from django.utils.translation import gettext_lazy as _ + from dcim.models import PowerFeed, PowerPanel +from netbox.tables import PrimaryModelTable, columns from tenancy.tables import ContactsColumnMixin, TenancyColumnsMixin - -from netbox.tables import NetBoxTable, columns - from .devices import CableTerminationTable __all__ = ( @@ -17,7 +16,7 @@ __all__ = ( # Power panels # -class PowerPanelTable(ContactsColumnMixin, NetBoxTable): +class PowerPanelTable(ContactsColumnMixin, PrimaryModelTable): name = tables.Column( verbose_name=_('Name'), linkify=True @@ -35,14 +34,11 @@ class PowerPanelTable(ContactsColumnMixin, NetBoxTable): url_params={'power_panel_id': 'pk'}, verbose_name=_('Power Feeds') ) - comments = columns.MarkdownColumn( - verbose_name=_('Comments'), - ) tags = columns.TagColumn( url_name='dcim:powerpanel_list' ) - class Meta(NetBoxTable.Meta): + class Meta(PrimaryModelTable.Meta): model = PowerPanel fields = ( 'pk', 'id', 'name', 'site', 'location', 'powerfeed_count', 'contacts', 'description', 'comments', 'tags', @@ -57,7 +53,7 @@ class PowerPanelTable(ContactsColumnMixin, NetBoxTable): # We're not using PathEndpointTable for PowerFeed because power connections # cannot traverse pass-through ports. -class PowerFeedTable(TenancyColumnsMixin, CableTerminationTable): +class PowerFeedTable(TenancyColumnsMixin, CableTerminationTable, PrimaryModelTable): name = tables.Column( verbose_name=_('Name'), linkify=True @@ -92,14 +88,11 @@ class PowerFeedTable(TenancyColumnsMixin, CableTerminationTable): linkify=True, verbose_name=_('Site'), ) - comments = columns.MarkdownColumn( - verbose_name=_('Comments'), - ) tags = columns.TagColumn( url_name='dcim:powerfeed_list' ) - class Meta(NetBoxTable.Meta): + class Meta(CableTerminationTable.Meta, PrimaryModelTable.Meta): model = PowerFeed fields = ( 'pk', 'id', 'name', 'power_panel', 'site', 'rack', 'status', 'type', 'supply', 'voltage', 'amperage', diff --git a/netbox/dcim/tables/racks.py b/netbox/dcim/tables/racks.py index afb2c44c8..1cc774f22 100644 --- a/netbox/dcim/tables/racks.py +++ b/netbox/dcim/tables/racks.py @@ -1,9 +1,9 @@ -from django.utils.translation import gettext_lazy as _ import django_tables2 as tables +from django.utils.translation import gettext_lazy as _ from django_tables2.utils import Accessor from dcim.models import Rack, RackReservation, RackRole, RackType -from netbox.tables import NetBoxTable, columns +from netbox.tables import OrganizationalModelTable, PrimaryModelTable, columns from tenancy.tables import ContactsColumnMixin, TenancyColumnsMixin from .template_code import OUTER_UNIT, WEIGHT @@ -15,11 +15,7 @@ __all__ = ( ) -# -# Rack roles -# - -class RackRoleTable(NetBoxTable): +class RackRoleTable(OrganizationalModelTable): name = tables.Column( verbose_name=_('Name'), linkify=True @@ -36,7 +32,7 @@ class RackRoleTable(NetBoxTable): url_name='dcim:rackrole_list' ) - class Meta(NetBoxTable.Meta): + class Meta(OrganizationalModelTable.Meta): model = RackRole fields = ( 'pk', 'id', 'name', 'rack_count', 'color', 'description', 'slug', 'tags', 'actions', 'created', @@ -45,11 +41,7 @@ class RackRoleTable(NetBoxTable): default_columns = ('pk', 'name', 'rack_count', 'color', 'description') -# -# Rack Types -# - -class RackTypeTable(NetBoxTable): +class RackTypeTable(PrimaryModelTable): model = tables.Column( verbose_name=_('Model'), linkify=True @@ -84,9 +76,6 @@ class RackTypeTable(NetBoxTable): template_code=WEIGHT, order_by=('_abs_max_weight', 'weight_unit') ) - comments = columns.MarkdownColumn( - verbose_name=_('Comments'), - ) instance_count = columns.LinkedCountColumn( viewname='dcim:rack_list', url_params={'rack_type_id': 'pk'}, @@ -96,7 +85,7 @@ class RackTypeTable(NetBoxTable): url_name='dcim:rack_list' ) - class Meta(NetBoxTable.Meta): + class Meta(PrimaryModelTable.Meta): model = RackType fields = ( 'pk', 'id', 'model', 'manufacturer', 'form_factor', 'u_height', 'starting_unit', 'width', 'outer_width', @@ -108,11 +97,7 @@ class RackTypeTable(NetBoxTable): ) -# -# Racks -# - -class RackTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable): +class RackTable(TenancyColumnsMixin, ContactsColumnMixin, PrimaryModelTable): name = tables.Column( verbose_name=_('Name'), linkify=True @@ -144,9 +129,6 @@ class RackTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable): template_code="{{ value }}U", verbose_name=_('Height') ) - comments = columns.MarkdownColumn( - verbose_name=_('Comments'), - ) device_count = columns.LinkedCountColumn( viewname='dcim:device_list', url_params={'rack_id': 'pk'}, @@ -186,7 +168,7 @@ class RackTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable): order_by=('_abs_max_weight', 'weight_unit') ) - class Meta(NetBoxTable.Meta): + class Meta(PrimaryModelTable.Meta): model = Rack fields = ( 'pk', 'id', 'name', 'site', 'location', 'status', 'facility_id', 'tenant', 'tenant_group', 'role', @@ -201,11 +183,7 @@ class RackTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable): ) -# -# Rack reservations -# - -class RackReservationTable(TenancyColumnsMixin, NetBoxTable): +class RackReservationTable(TenancyColumnsMixin, PrimaryModelTable): reservation = tables.Column( verbose_name=_('Reservation'), accessor='pk', @@ -232,14 +210,11 @@ class RackReservationTable(TenancyColumnsMixin, NetBoxTable): status = columns.ChoiceFieldColumn( verbose_name=_('Status'), ) - comments = columns.MarkdownColumn( - verbose_name=_('Comments'), - ) tags = columns.TagColumn( url_name='dcim:rackreservation_list' ) - class Meta(NetBoxTable.Meta): + class Meta(PrimaryModelTable.Meta): model = RackReservation fields = ( 'pk', 'id', 'reservation', 'site', 'location', 'rack', 'unit_list', 'status', 'user', 'created', 'tenant', diff --git a/netbox/dcim/tables/sites.py b/netbox/dcim/tables/sites.py index 0f8fb9372..544fb3cf8 100644 --- a/netbox/dcim/tables/sites.py +++ b/netbox/dcim/tables/sites.py @@ -1,10 +1,9 @@ -from django.utils.translation import gettext_lazy as _ import django_tables2 as tables +from django.utils.translation import gettext_lazy as _ + from dcim.models import Location, Region, Site, SiteGroup +from netbox.tables import NestedGroupModelTable, PrimaryModelTable, columns from tenancy.tables import ContactsColumnMixin, TenancyColumnsMixin - -from netbox.tables import NetBoxTable, columns - from .template_code import LOCATION_BUTTONS __all__ = ( @@ -15,19 +14,7 @@ __all__ = ( ) -# -# Regions -# - -class RegionTable(ContactsColumnMixin, NetBoxTable): - name = columns.MPTTColumn( - verbose_name=_('Name'), - linkify=True - ) - parent = tables.Column( - verbose_name=_('Parent'), - linkify=True, - ) +class RegionTable(ContactsColumnMixin, NestedGroupModelTable): site_count = columns.LinkedCountColumn( viewname='dcim:site_list', url_params={'region_id': 'pk'}, @@ -36,11 +23,8 @@ class RegionTable(ContactsColumnMixin, NetBoxTable): tags = columns.TagColumn( url_name='dcim:region_list' ) - comments = columns.MarkdownColumn( - verbose_name=_('Comments'), - ) - class Meta(NetBoxTable.Meta): + class Meta(NestedGroupModelTable.Meta): model = Region fields = ( 'pk', 'id', 'name', 'parent', 'slug', 'site_count', 'description', 'comments', 'contacts', 'tags', @@ -49,19 +33,7 @@ class RegionTable(ContactsColumnMixin, NetBoxTable): default_columns = ('pk', 'name', 'site_count', 'description') -# -# Site groups -# - -class SiteGroupTable(ContactsColumnMixin, NetBoxTable): - name = columns.MPTTColumn( - verbose_name=_('Name'), - linkify=True - ) - parent = tables.Column( - verbose_name=_('Parent'), - linkify=True, - ) +class SiteGroupTable(ContactsColumnMixin, NestedGroupModelTable): site_count = columns.LinkedCountColumn( viewname='dcim:site_list', url_params={'group_id': 'pk'}, @@ -70,11 +42,8 @@ class SiteGroupTable(ContactsColumnMixin, NetBoxTable): tags = columns.TagColumn( url_name='dcim:sitegroup_list' ) - comments = columns.MarkdownColumn( - verbose_name=_('Comments'), - ) - class Meta(NetBoxTable.Meta): + class Meta(NestedGroupModelTable.Meta): model = SiteGroup fields = ( 'pk', 'id', 'name', 'parent', 'slug', 'site_count', 'description', 'comments', 'contacts', 'tags', @@ -83,11 +52,7 @@ class SiteGroupTable(ContactsColumnMixin, NetBoxTable): default_columns = ('pk', 'name', 'site_count', 'description') -# -# Sites -# - -class SiteTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable): +class SiteTable(TenancyColumnsMixin, ContactsColumnMixin, PrimaryModelTable): name = tables.Column( verbose_name=_('Name'), linkify=True @@ -117,14 +82,11 @@ class SiteTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable): url_params={'site_id': 'pk'}, verbose_name=_('Devices') ) - comments = columns.MarkdownColumn( - verbose_name=_('Comments'), - ) tags = columns.TagColumn( url_name='dcim:site_list' ) - class Meta(NetBoxTable.Meta): + class Meta(PrimaryModelTable.Meta): model = Site fields = ( 'pk', 'id', 'name', 'slug', 'status', 'facility', 'region', 'group', 'tenant', 'tenant_group', 'asns', @@ -134,19 +96,7 @@ class SiteTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable): default_columns = ('pk', 'name', 'status', 'facility', 'region', 'group', 'tenant', 'description') -# -# Locations -# - -class LocationTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable): - name = columns.MPTTColumn( - verbose_name=_('Name'), - linkify=True - ) - parent = tables.Column( - verbose_name=_('Parent'), - linkify=True, - ) +class LocationTable(TenancyColumnsMixin, ContactsColumnMixin, NestedGroupModelTable): site = tables.Column( verbose_name=_('Site'), linkify=True @@ -175,11 +125,8 @@ class LocationTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable): actions = columns.ActionsColumn( extra_buttons=LOCATION_BUTTONS ) - comments = columns.MarkdownColumn( - verbose_name=_('Comments'), - ) - class Meta(NetBoxTable.Meta): + class Meta(NestedGroupModelTable.Meta): model = Location fields = ( 'pk', 'id', 'name', 'parent', 'site', 'status', 'facility', 'tenant', 'tenant_group', 'rack_count', diff --git a/netbox/extras/tables/tables.py b/netbox/extras/tables/tables.py index e89d06c40..40f43b527 100644 --- a/netbox/extras/tables/tables.py +++ b/netbox/extras/tables/tables.py @@ -10,7 +10,7 @@ from core.tables import JobTable from core.models import Job from netbox.constants import EMPTY_TABLE_TEXT from netbox.events import get_event_text -from netbox.tables import BaseTable, NetBoxTable, columns +from netbox.tables import BaseTable, NetBoxTable, PrimaryModelTable, columns from .columns import NotificationActionsColumn __all__ = ( @@ -109,6 +109,10 @@ class CustomFieldTable(NetBoxTable): validation_regex = tables.Column( verbose_name=_('Validation Regex'), ) + owner = tables.Column( + linkify=True, + verbose_name=_('Owner') + ) class Meta(NetBoxTable.Meta): model = CustomField @@ -146,6 +150,10 @@ class CustomFieldChoiceSetTable(NetBoxTable): verbose_name=_('Order Alphabetically'), false_mark=None ) + owner = tables.Column( + linkify=True, + verbose_name=_('Owner') + ) class Meta(NetBoxTable.Meta): model = CustomFieldChoiceSet @@ -171,6 +179,10 @@ class CustomLinkTable(NetBoxTable): verbose_name=_('New Window'), false_mark=None ) + owner = tables.Column( + linkify=True, + verbose_name=_('Owner') + ) class Meta(NetBoxTable.Meta): model = CustomLink @@ -214,6 +226,10 @@ class ExportTemplateTable(NetBoxTable): orderable=False, verbose_name=_('Synced') ) + owner = tables.Column( + linkify=True, + verbose_name=_('Owner') + ) class Meta(NetBoxTable.Meta): model = ExportTemplate @@ -294,6 +310,10 @@ class SavedFilterTable(NetBoxTable): verbose_name=_('Shared'), false_mark=None ) + owner = tables.Column( + linkify=True, + verbose_name=_('Owner') + ) def value_parameters(self, value): return json.dumps(value) @@ -450,6 +470,10 @@ class WebhookTable(NetBoxTable): ssl_validation = columns.BooleanColumn( verbose_name=_('SSL Validation') ) + owner = tables.Column( + linkify=True, + verbose_name=_('Owner') + ) tags = columns.TagColumn( url_name='extras:webhook_list' ) @@ -488,6 +512,10 @@ class EventRuleTable(NetBoxTable): func=get_event_text, orderable=False ) + owner = tables.Column( + linkify=True, + verbose_name=_('Owner') + ) tags = columns.TagColumn( url_name='extras:webhook_list' ) @@ -514,6 +542,10 @@ class TagTable(NetBoxTable): object_types = columns.ContentTypesColumn( verbose_name=_('Object Types'), ) + owner = tables.Column( + linkify=True, + verbose_name=_('Owner') + ) class Meta(NetBoxTable.Meta): model = Tag @@ -547,7 +579,7 @@ class TaggedItemTable(NetBoxTable): fields = ('id', 'content_type', 'content_object') -class ConfigContextProfileTable(NetBoxTable): +class ConfigContextProfileTable(PrimaryModelTable): name = tables.Column( verbose_name=_('Name'), linkify=True @@ -568,7 +600,7 @@ class ConfigContextProfileTable(NetBoxTable): url_name='extras:configcontextprofile_list' ) - class Meta(NetBoxTable.Meta): + class Meta(PrimaryModelTable.Meta): model = ConfigContextProfile fields = ( 'pk', 'id', 'name', 'description', 'comments', 'data_source', 'data_file', 'is_synced', 'tags', 'created', @@ -601,6 +633,10 @@ class ConfigContextTable(NetBoxTable): orderable=False, verbose_name=_('Synced') ) + owner = tables.Column( + linkify=True, + verbose_name=_('Owner') + ) tags = columns.TagColumn( url_name='extras:configcontext_list' ) @@ -645,6 +681,10 @@ class ConfigTemplateTable(NetBoxTable): verbose_name=_('As Attachment'), false_mark=None ) + owner = tables.Column( + linkify=True, + verbose_name=_('Owner') + ) tags = columns.TagColumn( url_name='extras:configtemplate_list' ) diff --git a/netbox/ipam/tables/asn.py b/netbox/ipam/tables/asn.py index bbe38dc1a..0f9c357ad 100644 --- a/netbox/ipam/tables/asn.py +++ b/netbox/ipam/tables/asn.py @@ -2,7 +2,7 @@ import django_tables2 as tables from django.utils.translation import gettext_lazy as _ from ipam.models import * -from netbox.tables import NetBoxTable, columns +from netbox.tables import OrganizationalModelTable, PrimaryModelTable, columns from tenancy.tables import TenancyColumnsMixin __all__ = ( @@ -11,7 +11,7 @@ __all__ = ( ) -class ASNRangeTable(TenancyColumnsMixin, NetBoxTable): +class ASNRangeTable(TenancyColumnsMixin, OrganizationalModelTable): name = tables.Column( verbose_name=_('Name'), linkify=True @@ -27,7 +27,7 @@ class ASNRangeTable(TenancyColumnsMixin, NetBoxTable): verbose_name=_('ASNs') ) - class Meta(NetBoxTable.Meta): + class Meta(OrganizationalModelTable.Meta): model = ASNRange fields = ( 'pk', 'name', 'slug', 'rir', 'start', 'end', 'asn_count', 'tenant', 'tenant_group', 'description', 'tags', @@ -36,7 +36,7 @@ class ASNRangeTable(TenancyColumnsMixin, NetBoxTable): default_columns = ('pk', 'name', 'rir', 'start', 'end', 'tenant', 'asn_count', 'description') -class ASNTable(TenancyColumnsMixin, NetBoxTable): +class ASNTable(TenancyColumnsMixin, PrimaryModelTable): asn = tables.Column( verbose_name=_('ASN'), linkify=True @@ -65,14 +65,11 @@ class ASNTable(TenancyColumnsMixin, NetBoxTable): linkify_item=True, verbose_name=_('Sites') ) - comments = columns.MarkdownColumn( - verbose_name=_('Comments'), - ) tags = columns.TagColumn( url_name='ipam:asn_list' ) - class Meta(NetBoxTable.Meta): + class Meta(PrimaryModelTable.Meta): model = ASN fields = ( 'pk', 'asn', 'asn_asdot', 'rir', 'site_count', 'provider_count', 'tenant', 'tenant_group', 'description', diff --git a/netbox/ipam/tables/fhrp.py b/netbox/ipam/tables/fhrp.py index 789845f25..2d77c62c7 100644 --- a/netbox/ipam/tables/fhrp.py +++ b/netbox/ipam/tables/fhrp.py @@ -1,8 +1,8 @@ -from django.utils.translation import gettext_lazy as _ import django_tables2 as tables +from django.utils.translation import gettext_lazy as _ from ipam.models import * -from netbox.tables import NetBoxTable, columns +from netbox.tables import NetBoxTable, PrimaryModelTable, columns __all__ = ( 'FHRPGroupTable', @@ -17,7 +17,7 @@ IPADDRESSES = """ """ -class FHRPGroupTable(NetBoxTable): +class FHRPGroupTable(PrimaryModelTable): group_id = tables.Column( verbose_name=_('Group ID'), linkify=True @@ -30,9 +30,6 @@ class FHRPGroupTable(NetBoxTable): member_count = tables.Column( verbose_name=_('Members') ) - comments = columns.MarkdownColumn( - verbose_name=_('Comments'), - ) tags = columns.TagColumn( url_name='ipam:fhrpgroup_list' ) @@ -40,7 +37,7 @@ class FHRPGroupTable(NetBoxTable): def value_ip_addresses(self, value): return ",".join([str(obj.address) for obj in value.all()]) - class Meta(NetBoxTable.Meta): + class Meta(PrimaryModelTable.Meta): model = FHRPGroup fields = ( 'pk', 'group_id', 'protocol', 'name', 'auth_type', 'auth_key', 'description', 'comments', 'ip_addresses', diff --git a/netbox/ipam/tables/ip.py b/netbox/ipam/tables/ip.py index 03365a442..11387185a 100644 --- a/netbox/ipam/tables/ip.py +++ b/netbox/ipam/tables/ip.py @@ -1,10 +1,10 @@ -from django.utils.translation import gettext_lazy as _ import django_tables2 as tables from django.utils.safestring import mark_safe +from django.utils.translation import gettext_lazy as _ from django_tables2.utils import Accessor from ipam.models import * -from netbox.tables import NetBoxTable, columns +from netbox.tables import NetBoxTable, OrganizationalModelTable, PrimaryModelTable, columns from tenancy.tables import TenancyColumnsMixin, TenantColumn from .template_code import * @@ -27,7 +27,7 @@ AVAILABLE_LABEL = mark_safe('AvailableAvailable