Repository: netbox-community/netbox
Pull request: Closes #6930: Add 'ID' column to object tables
### Closes: #6930

Adds an 'ID' column to most object tables, which is hidden by default. This column exposes Netbox's numeric ID for that object.

![image](https://user-images.githubusercontent.com/3577982/139305629-4a3d08e0-e04f-4ef4-a994-6325d20767b4.png)

The column has been added to the following tables:
- Organization > Site, Region, Site Group, Location, Rack Role, Rack, Rack Reservations, Tenant, Rack Role, Rack, Rack Reservation
- Devices > Manufacturer, Device Type, Device Role, Platform, Device, Virtual Chassis
- Device Components > Console Port, Console Server Port, Power Port, Power Outlet, Interface, Front Port, Rear Port, Device Bay, Inventory item
- IPAM > IP Addresses, IP Ranges, Prefixes, Prefix & VLAN Roles, VRFs, Route Targets, VLANs, VLAN Groups, Services
- Virtualization > Virtual Machines, VM Interfaces, Clusters, Cluster Types, Cluster Groups
- Circuits > Circuit Types, Providers, Provider Networks
- Power > Power Feeds, Power Panels
- Other > Journal Entries, Change Log Entries, Custom Fields, Custom Links, Export Templates, Webhooks, Tags, Config Contexts

Regarding the "Circuits" table, this already exposes the circuit ID under the 'ID' header. My thought would be to change the circuit ID header to 'Circuit ID', and then add the Netbox 'ID' column, but this could potentially break anything that consumes the CSV exports, and thus would need to wait for v3.1.0.

Problem statement:
Add ID as an exportable column for all object tables
### NetBox version

v2.11.9

### Feature type

Change to existing functionality

### Proposed functionality

It would be nice, if we can export the device ID (or even the complete URL) into a csv files using the already available export csv feature.

### Use case

We would like to add the netbox URL into our CMDB to provide direct links.

Can be also useful for other usecases, if you can export the ID.

### Database changes

_No response_

### External dependencies

_No response_

Hints from issue discussion:
You can make a custom export template that can contain all the fields you could ever wish for.
Did you try that functionality?

[Export Templates - Netbox docs](https://netbox.readthedocs.io/en/stable/additional-features/export-templates/)
Not yet, but I will definitely have a look at this. Thanks for the hint. 
Checkout the webhooks as well, if you try to do more then a one-off /manual sync between netbox and another system
FWIW we could add an "ID" column to all object tables pretty easily, I think. It would be hidden by default but available.
@sdktr I finaly realized how to use these export templates. that totally fits our needs.
@jeremystretch I can implement this if you want to assign this issue to me.
Thanks @rhyser9!

Commit message: netbox-community/netbox#6930:revert default columns on ObjectChangeTable, not configurable

Patch to review:
diff --git a/netbox/circuits/tables.py b/netbox/circuits/tables.py
index 2e31237b69c..847d44ffd5b 100644
--- a/netbox/circuits/tables.py
+++ b/netbox/circuits/tables.py
@@ -44,8 +44,8 @@ class ProviderTable(BaseTable):
     class Meta(BaseTable.Meta):
         model = Provider
         fields = (
-            'pk', 'name', 'asn', 'account', 'portal_url', 'noc_contact', 'admin_contact', 'circuit_count', 'comments',
-            'tags',
+            'pk', 'id', 'name', 'asn', 'account', 'portal_url', 'noc_contact', 'admin_contact', 'circuit_count',
+            'comments', 'tags',
         )
         default_columns = ('pk', 'name', 'asn', 'account', 'circuit_count')
 
@@ -69,7 +69,7 @@ class ProviderNetworkTable(BaseTable):
 
     class Meta(BaseTable.Meta):
         model = ProviderNetwork
-        fields = ('pk', 'name', 'provider', 'description', 'comments', 'tags')
+        fields = ('pk', 'id', 'name', 'provider', 'description', 'comments', 'tags')
         default_columns = ('pk', 'name', 'provider', 'description')
 
 
@@ -89,7 +89,7 @@ class CircuitTypeTable(BaseTable):
 
     class Meta(BaseTable.Meta):
         model = CircuitType
-        fields = ('pk', 'name', 'circuit_count', 'description', 'slug', 'actions')
+        fields = ('pk', 'id', 'name', 'circuit_count', 'description', 'slug', 'actions')
         default_columns = ('pk', 'name', 'circuit_count', 'description', 'slug', 'actions')
 
 
@@ -124,7 +124,7 @@ class CircuitTable(BaseTable):
     class Meta(BaseTable.Meta):
         model = Circuit
         fields = (
-            'pk', 'cid', 'provider', 'type', 'status', 'tenant', 'termination_a', 'termination_z', 'install_date',
+            'pk', 'id', 'cid', 'provider', 'type', 'status', 'tenant', 'termination_a', 'termination_z', 'install_date',
             'commit_rate', 'description', 'comments', 'tags',
         )
         default_columns = (
diff --git a/netbox/dcim/tables/__init__.py b/netbox/dcim/tables/__init__.py
index 8a861c8c20f..825e60d57b0 100644
--- a/netbox/dcim/tables/__init__.py
+++ b/netbox/dcim/tables/__init__.py
@@ -43,6 +43,7 @@ class ConsoleConnectionTable(BaseTable):
     class Meta(BaseTable.Meta):
         model = ConsolePort
         fields = ('device', 'name', 'console_server', 'console_server_port', 'reachable')
+        exclude = ('id', )
 
 
 class PowerConnectionTable(BaseTable):
@@ -73,6 +74,7 @@ class PowerConnectionTable(BaseTable):
     class Meta(BaseTable.Meta):
         model = PowerPort
         fields = ('device', 'name', 'pdu', 'outlet', 'reachable')
+        exclude = ('id', )
 
 
 class InterfaceConnectionTable(BaseTable):
@@ -106,3 +108,4 @@ class InterfaceConnectionTable(BaseTable):
     class Meta(BaseTable.Meta):
         model = Interface
         fields = ('device_a', 'interface_a', 'device_b', 'interface_b', 'reachable')
+        exclude = ('id', )
diff --git a/netbox/dcim/tables/cables.py b/netbox/dcim/tables/cables.py
index 14cf3450514..5533c45280c 100644
--- a/netbox/dcim/tables/cables.py
+++ b/netbox/dcim/tables/cables.py
@@ -16,10 +16,6 @@
 
 class CableTable(BaseTable):
     pk = ToggleColumn()
-    id = tables.Column(
-        linkify=True,
-        verbose_name='ID'
-    )
     termination_a_parent = tables.TemplateColumn(
         template_code=CABLE_TERMINATION_PARENT,
         accessor=Accessor('termination_a'),
diff --git a/netbox/dcim/tables/devices.py b/netbox/dcim/tables/devices.py
index c22e673b78c..675f7d7776d 100644
--- a/netbox/dcim/tables/devices.py
+++ b/netbox/dcim/tables/devices.py
@@ -88,7 +88,7 @@ class DeviceRoleTable(BaseTable):
 
     class Meta(BaseTable.Meta):
         model = DeviceRole
-        fields = ('pk', 'name', 'device_count', 'vm_count', 'color', 'vm_role', 'description', 'slug', 'actions')
+        fields = ('pk', 'id', 'name', 'device_count', 'vm_count', 'color', 'vm_role', 'description', 'slug', 'actions')
         default_columns = ('pk', 'name', 'device_count', 'vm_count', 'color', 'vm_role', 'description', 'actions')
 
 
@@ -116,7 +116,7 @@ class PlatformTable(BaseTable):
     class Meta(BaseTable.Meta):
         model = Platform
         fields = (
-            'pk', 'name', 'manufacturer', 'device_count', 'vm_count', 'slug', 'napalm_driver', 'napalm_args',
+            'pk', 'id', 'name', 'manufacturer', 'device_count', 'vm_count', 'slug', 'napalm_driver', 'napalm_args',
             'description', 'actions',
         )
         default_columns = (
@@ -196,7 +196,7 @@ class DeviceTable(BaseTable):
     class Meta(BaseTable.Meta):
         model = Device
         fields = (
-            'pk', 'name', 'status', 'tenant', 'device_role', 'manufacturer', 'device_type', 'platform', 'serial',
+            'pk', 'id', 'name', 'status', 'tenant', 'device_role', 'manufacturer', 'device_type', 'platform', 'serial',
             'asset_tag', 'site', 'location', 'rack', 'position', 'face', 'primary_ip', 'primary_ip4', 'primary_ip6',
             'cluster', 'virtual_chassis', 'vc_position', 'vc_priority', 'comments', 'tags',
         )
@@ -227,7 +227,7 @@ class DeviceImportTable(BaseTable):
 
     class Meta(BaseTable.Meta):
         model = Device
-        fields = ('name', 'status', 'tenant', 'site', 'rack', 'position', 'device_role', 'device_type')
+        fields = ('id', 'name', 'status', 'tenant', 'site', 'rack', 'position', 'device_role', 'device_type')
         empty_text = False
 
 
@@ -290,7 +290,7 @@ class ConsolePortTable(DeviceComponentTable, PathEndpointTable):
     class Meta(DeviceComponentTable.Meta):
         model = ConsolePort
         fields = (
-            'pk', 'name', 'device', 'label', 'type', 'speed', 'description', 'mark_connected', 'cable', 'cable_color',
+            'pk', 'id', 'name', 'device', 'label', 'type', 'speed', 'description', 'mark_connected', 'cable', 'cable_color',
             'cable_peer', 'connection', 'tags',
         )
         default_columns = ('pk', 'name', 'device', 'label', 'type', 'speed', 'description')
@@ -311,7 +311,7 @@ class DeviceConsolePortTable(ConsolePortTable):
     class Meta(DeviceComponentTable.Meta):
         model = ConsolePort
         fields = (
-            'pk', 'name', 'label', 'type', 'speed', 'description', 'mark_connected', 'cable', 'cable_color',
+            'pk', 'id', 'name', 'label', 'type', 'speed', 'description', 'mark_connected', 'cable', 'cable_color',
             'cable_peer', 'connection', 'tags', 'actions'
         )
         default_columns = ('pk', 'name', 'label', 'type', 'speed', 'description', 'cable', 'connection', 'actions')
@@ -334,7 +334,7 @@ class ConsoleServerPortTable(DeviceComponentTable, PathEndpointTable):
     class Meta(DeviceComponentTable.Meta):
         model = ConsoleServerPort
         fields = (
-            'pk', 'name', 'device', 'label', 'type', 'speed', 'description', 'mark_connected', 'cable', 'cable_color',
+            'pk', 'id', 'name', 'device', 'label', 'type', 'speed', 'description', 'mark_connected', 'cable', 'cable_color',
             'cable_peer', 'connection', 'tags',
         )
         default_columns = ('pk', 'name', 'device', 'label', 'type', 'speed', 'description')
@@ -356,7 +356,7 @@ class DeviceConsoleServerPortTable(ConsoleServerPortTable):
     class Meta(DeviceComponentTable.Meta):
         model = ConsoleServerPort
         fields = (
-            'pk', 'name', 'label', 'type', 'speed', 'description', 'mark_connected', 'cable', 'cable_color',
+            'pk', 'id', 'name', 'label', 'type', 'speed', 'description', 'mark_connected', 'cable', 'cable_color',
             'cable_peer', 'connection', 'tags', 'actions',
         )
         default_columns = ('pk', 'name', 'label', 'type', 'speed', 'description', 'cable', 'connection', 'actions')
@@ -379,7 +379,7 @@ class PowerPortTable(DeviceComponentTable, PathEndpointTable):
     class Meta(DeviceComponentTable.Meta):
         model = PowerPort
         fields = (
-            'pk', 'name', 'device', 'label', 'type', 'description', 'mark_connected', 'maximum_draw', 'allocated_draw',
+            'pk', 'id', 'name', 'device', 'label', 'type', 'description', 'mark_connected', 'maximum_draw', 'allocated_draw',
             'cable', 'cable_color', 'cable_peer', 'connection', 'tags',
         )
         default_columns = ('pk', 'name', 'device', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description')
@@ -401,7 +401,7 @@ class DevicePowerPortTable(PowerPortTable):
     class Meta(DeviceComponentTable.Meta):
         model = PowerPort
         fields = (
-            'pk', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description', 'mark_connected', 'cable',
+            'pk', 'id', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description', 'mark_connected', 'cable',
             'cable_color', 'cable_peer', 'connection', 'tags', 'actions',
         )
         default_columns = (
@@ -430,7 +430,7 @@ class PowerOutletTable(DeviceComponentTable, PathEndpointTable):
     class Meta(DeviceComponentTable.Meta):
         model = PowerOutlet
         fields = (
-            'pk', 'name', 'device', 'label', 'type', 'description', 'power_port', 'feed_leg', 'mark_connected', 'cable',
+            'pk', 'id', 'name', 'device', 'label', 'type', 'description', 'power_port', 'feed_leg', 'mark_connected', 'cable',
             'cable_color', 'cable_peer', 'connection', 'tags',
         )
         default_columns = ('pk', 'name', 'device', 'label', 'type', 'power_port', 'feed_leg', 'description')
@@ -451,7 +451,7 @@ class DevicePowerOutletTable(PowerOutletTable):
     class Meta(DeviceComponentTable.Meta):
         model = PowerOutlet
         fields = (
-            'pk', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description', 'mark_connected', 'cable',
+            'pk', 'id', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description', 'mark_connected', 'cable',
             'cable_color', 'cable_peer', 'connection', 'tags', 'actions',
         )
         default_columns = (
@@ -492,7 +492,7 @@ class InterfaceTable(DeviceComponentTable, BaseInterfaceTable, PathEndpointTable
     class Meta(DeviceComponentTable.Meta):
         model = Interface
         fields = (
-            'pk', 'name', 'device', 'label', 'enabled', 'type', 'mgmt_only', 'mtu', 'mode', 'mac_address',
+            'pk', 'id', 'name', 'device', 'label', 'enabled', 'type', 'mgmt_only', 'mtu', 'mode', 'mac_address',
             'description', 'mark_connected', 'cable', 'cable_color', 'cable_peer', 'connection', 'tags', 'ip_addresses',
             'untagged_vlan', 'tagged_vlans',
         )
@@ -524,7 +524,7 @@ class DeviceInterfaceTable(InterfaceTable):
     class Meta(DeviceComponentTable.Meta):
         model = Interface
         fields = (
-            'pk', 'name', 'label', 'enabled', 'type', 'parent', 'lag', 'mgmt_only', 'mtu', 'mode', 'mac_address',
+            'pk', 'id', 'name', 'label', 'enabled', 'type', 'parent', 'lag', 'mgmt_only', 'mtu', 'mode', 'mac_address',
             'description', 'mark_connected', 'cable', 'cable_color', 'cable_peer', 'connection', 'tags', 'ip_addresses',
             'untagged_vlan', 'tagged_vlans', 'actions',
         )
@@ -561,7 +561,7 @@ class FrontPortTable(DeviceComponentTable, CableTerminationTable):
     class Meta(DeviceComponentTable.Meta):
         model = FrontPort
         fields = (
-            'pk', 'name', 'device', 'label', 'type', 'color', 'rear_port', 'rear_port_position', 'description',
+            'pk', 'id', 'name', 'device', 'label', 'type', 'color', 'rear_port', 'rear_port_position', 'description',
             'mark_connected', 'cable', 'cable_color', 'cable_peer', 'tags',
         )
         default_columns = (
@@ -585,7 +585,7 @@ class DeviceFrontPortTable(FrontPortTable):
     class Meta(DeviceComponentTable.Meta):
         model = FrontPort
         fields = (
-            'pk', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'mark_connected', 'cable',
+            'pk', 'id', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'mark_connected', 'cable',
             'cable_color', 'cable_peer', 'tags', 'actions',
         )
         default_columns = (
@@ -612,7 +612,7 @@ class RearPortTable(DeviceComponentTable, CableTerminationTable):
     class Meta(DeviceComponentTable.Meta):
         model = RearPort
         fields = (
-            'pk', 'name', 'device', 'label', 'type', 'color', 'positions', 'description', 'mark_connected', 'cable',
+            'pk', 'id', 'name', 'device', 'label', 'type', 'color', 'positions', 'description', 'mark_connected', 'cable',
             'cable_color', 'cable_peer', 'tags',
         )
         default_columns = ('pk', 'name', 'device', 'label', 'type', 'color', 'description')
@@ -634,7 +634,7 @@ class DeviceRearPortTable(RearPortTable):
     class Meta(DeviceComponentTable.Meta):
         model = RearPort
         fields = (
-            'pk', 'name', 'label', 'type', 'positions', 'description', 'mark_connected', 'cable', 'cable_color',
+            'pk', 'id', 'name', 'label', 'type', 'positions', 'description', 'mark_connected', 'cable', 'cable_color',
             'cable_peer', 'tags', 'actions',
         )
         default_columns = (
@@ -664,7 +664,7 @@ class DeviceBayTable(DeviceComponentTable):
 
     class Meta(DeviceComponentTable.Meta):
         model = DeviceBay
-        fields = ('pk', 'name', 'device', 'label', 'status', 'installed_device', 'description', 'tags')
+        fields = ('pk', 'id', 'name', 'device', 'label', 'status', 'installed_device', 'description', 'tags')
         default_columns = ('pk', 'name', 'device', 'label', 'status', 'installed_device', 'description')
 
 
@@ -684,7 +684,7 @@ class DeviceDeviceBayTable(DeviceBayTable):
     class Meta(DeviceComponentTable.Meta):
         model = DeviceBay
         fields = (
-            'pk', 'name', 'label', 'status', 'installed_device', 'description', 'tags', 'actions',
+            'pk', 'id', 'name', 'label', 'status', 'installed_device', 'description', 'tags', 'actions',
         )
         default_columns = (
             'pk', 'name', 'label', 'status', 'installed_device', 'description', 'actions',
@@ -710,7 +710,7 @@ class InventoryItemTable(DeviceComponentTable):
     class Meta(BaseTable.Meta):
         model = InventoryItem
         fields = (
-            'pk', 'name', 'device', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description',
+            'pk', 'id', 'name', 'device', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description',
             'discovered', 'tags',
         )
         default_columns = ('pk', 'name', 'device', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag')
@@ -731,7 +731,7 @@ class DeviceInventoryItemTable(InventoryItemTable):
     class Meta(BaseTable.Meta):
         model = InventoryItem
         fields = (
-            'pk', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description', 'discovered',
+            'pk', 'id', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description', 'discovered',
             'tags', 'actions',
         )
         default_columns = (
@@ -763,5 +763,5 @@ class VirtualChassisTable(BaseTable):
 
     class Meta(BaseTable.Meta):
         model = VirtualChassis
-        fields = ('pk', 'name', 'domain', 'master', 'member_count', 'tags')
+        fields = ('pk', 'id', 'name', 'domain', 'master', 'member_count', 'tags')
         default_columns = ('pk', 'name', 'domain', 'master', 'member_count')
diff --git a/netbox/dcim/tables/devicetypes.py b/netbox/dcim/tables/devicetypes.py
index 3b11a180b35..d176d3ff662 100644
--- a/netbox/dcim/tables/devicetypes.py
+++ b/netbox/dcim/tables/devicetypes.py
@@ -46,6 +46,9 @@ class ManufacturerTable(BaseTable):
     class Meta(BaseTable.Meta):
         model = Manufacturer
         fields = (
+            'pk', 'id', 'name', 'devicetype_count', 'inventoryitem_count', 'platform_count', 'description', 'slug', 'actions',
+        )
+        default_columns = (
             'pk', 'name', 'devicetype_count', 'inventoryitem_count', 'platform_count', 'description', 'slug', 'actions',
         )
 
@@ -76,7 +79,7 @@ class DeviceTypeTable(BaseTable):
     class Meta(BaseTable.Meta):
         model = DeviceType
         fields = (
-            'pk', 'model', 'manufacturer', 'slug', 'part_number', 'u_height', 'is_full_depth', 'subdevice_role',
+            'pk', 'id', 'model', 'manufacturer', 'slug', 'part_number', 'u_height', 'is_full_depth', 'subdevice_role',
             'comments', 'instance_count', 'tags',
         )
         default_columns = (
@@ -90,10 +93,16 @@ class Meta(BaseTable.Meta):
 
 class ComponentTemplateTable(BaseTable):
     pk = ToggleColumn()
+    id = tables.Column(
+        verbose_name='ID'
+    )
     name = tables.Column(
         order_by=('_name',)
     )
 
+    class Meta(BaseTable.Meta):
+        exclude = ('id', )
+
 
 class ConsolePortTemplateTable(ComponentTemplateTable):
     actions = ButtonsColumn(
@@ -102,7 +111,7 @@ class ConsolePortTemplateTable(ComponentTemplateTable):
         return_url_extra='%23tab_consoleports'
     )
 
-    class Meta(BaseTable.Meta):
+    class Meta(ComponentTemplateTable.Meta):
         model = ConsolePortTemplate
         fields = ('pk', 'name', 'label', 'type', 'description', 'actions')
         empty_text = "None"
@@ -115,7 +124,7 @@ class ConsoleServerPortTemplateTable(ComponentTemplateTable):
         return_url_extra='%23tab_consoleserverports'
     )
 
-    class Meta(BaseTable.Meta):
+    class Meta(ComponentTemplateTable.Meta):
         model = ConsoleServerPortTemplate
         fields = ('pk', 'name', 'label', 'type', 'description', 'actions')
         empty_text = "None"
@@ -128,7 +137,7 @@ class PowerPortTemplateTable(ComponentTemplateTable):
         return_url_extra='%23tab_powerports'
     )
 
-    class Meta(BaseTable.Meta):
+    class Meta(ComponentTemplateTable.Meta):
         model = PowerPortTemplate
         fields = ('pk', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description', 'actions')
         empty_text = "None"
@@ -141,7 +150,7 @@ class PowerOutletTemplateTable(ComponentTemplateTable):
         return_url_extra='%23tab_poweroutlets'
     )
 
-    class Meta(BaseTable.Meta):
+    class Meta(ComponentTemplateTable.Meta):
         model = PowerOutletTemplate
         fields = ('pk', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description', 'actions')
         empty_text = "None"
@@ -157,7 +166,7 @@ class InterfaceTemplateTable(ComponentTemplateTable):
         return_url_extra='%23tab_interfaces'
     )
 
-    class Meta(BaseTable.Meta):
+    class Meta(ComponentTemplateTable.Meta):
         model = InterfaceTemplate
         fields = ('pk', 'name', 'label', 'mgmt_only', 'type', 'description', 'actions')
         empty_text = "None"
@@ -174,7 +183,7 @@ class FrontPortTemplateTable(ComponentTemplateTable):
         return_url_extra='%23tab_frontports'
     )
 
-    class Meta(BaseTable.Meta):
+    class Meta(ComponentTemplateTable.Meta):
         model = FrontPortTemplate
         fields = ('pk', 'name', 'label', 'type', 'color', 'rear_port', 'rear_port_position', 'description', 'actions')
         empty_text = "None"
@@ -188,7 +197,7 @@ class RearPortTemplateTable(ComponentTemplateTable):
         return_url_extra='%23tab_rearports'
     )
 
-    class Meta(BaseTable.Meta):
+    class Meta(ComponentTemplateTable.Meta):
         model = RearPortTemplate
         fields = ('pk', 'name', 'label', 'type', 'color', 'positions', 'description', 'actions')
         empty_text = "None"
@@ -201,7 +210,7 @@ class DeviceBayTemplateTable(ComponentTemplateTable):
         return_url_extra='%23tab_devicebays'
     )
 
-    class Meta(BaseTable.Meta):
+    class Meta(ComponentTemplateTable.Meta):
         model = DeviceBayTemplate
         fields = ('pk', 'name', 'label', 'description', 'actions')
         empty_text = "None"
diff --git a/netbox/dcim/tables/power.py b/netbox/dcim/tables/power.py
index b8e032e7ff0..955b27941c0 100644
--- a/netbox/dcim/tables/power.py
+++ b/netbox/dcim/tables/power.py
@@ -33,7 +33,7 @@ class PowerPanelTable(BaseTable):
 
     class Meta(BaseTable.Meta):
         model = PowerPanel
-        fields = ('pk', 'name', 'site', 'location', 'powerfeed_count', 'tags')
+        fields = ('pk', 'id', 'name', 'site', 'location', 'powerfeed_count', 'tags')
         default_columns = ('pk', 'name', 'site', 'location', 'powerfeed_count')
 
 
@@ -70,7 +70,7 @@ class PowerFeedTable(CableTerminationTable):
     class Meta(BaseTable.Meta):
         model = PowerFeed
         fields = (
-            'pk', 'name', 'power_panel', 'rack', 'status', 'type', 'supply', 'voltage', 'amperage', 'phase',
+            'pk', 'id', 'name', 'power_panel', 'rack', 'status', 'type', 'supply', 'voltage', 'amperage', 'phase',
             'max_utilization', 'mark_connected', 'cable', 'cable_color', 'cable_peer', 'connection', 'available_power',
             'comments', 'tags',
         )
diff --git a/netbox/dcim/tables/racks.py b/netbox/dcim/tables/racks.py
index fcc3ed4d231..f3d1cb7f84a 100644
--- a/netbox/dcim/tables/racks.py
+++ b/netbox/dcim/tables/racks.py
@@ -28,7 +28,7 @@ class RackRoleTable(BaseTable):
 
     class Meta(BaseTable.Meta):
         model = RackRole
-        fields = ('pk', 'name', 'rack_count', 'color', 'description', 'slug', 'actions')
+        fields = ('pk', 'id', 'name', 'rack_count', 'color', 'description', 'slug', 'actions')
         default_columns = ('pk', 'name', 'rack_count', 'color', 'description', 'actions')
 
 
@@ -76,7 +76,7 @@ class RackTable(BaseTable):
     class Meta(BaseTable.Meta):
         model = Rack
         fields = (
-            'pk', 'name', 'site', 'location', 'status', 'facility_id', 'tenant', 'role', 'serial', 'asset_tag', 'type',
+            'pk', 'id', 'name', 'site', 'location', 'status', 'facility_id', 'tenant', 'role', 'serial', 'asset_tag', 'type',
             'width', 'u_height', 'comments', 'device_count', 'get_utilization', 'get_power_utilization', 'tags',
         )
         default_columns = (
@@ -115,7 +115,7 @@ class RackReservationTable(BaseTable):
     class Meta(BaseTable.Meta):
         model = RackReservation
         fields = (
-            'pk', 'reservation', 'site', 'rack', 'unit_list', 'user', 'created', 'tenant', 'description', 'tags',
+            'pk', 'id', 'reservation', 'site', 'rack', 'unit_list', 'user', 'created', 'tenant', 'description', 'tags',
             'actions',
         )
         default_columns = (
diff --git a/netbox/dcim/tables/sites.py b/netbox/dcim/tables/sites.py
index 37fa019a16a..56180236dd5 100644
--- a/netbox/dcim/tables/sites.py
+++ b/netbox/dcim/tables/sites.py
@@ -33,7 +33,7 @@ class RegionTable(BaseTable):
 
     class Meta(BaseTable.Meta):
         model = Region
-        fields = ('pk', 'name', 'slug', 'site_count', 'description', 'actions')
+        fields = ('pk', 'id', 'name', 'slug', 'site_count', 'description', 'actions')
         default_columns = ('pk', 'name', 'site_count', 'description', 'actions')
 
 
@@ -55,7 +55,7 @@ class SiteGroupTable(BaseTable):
 
     class Meta(BaseTable.Meta):
         model = SiteGroup
-        fields = ('pk', 'name', 'slug', 'site_count', 'description', 'actions')
+        fields = ('pk', 'id', 'name', 'slug', 'site_count', 'description', 'actions')
         default_columns = ('pk', 'name', 'site_count', 'description', 'actions')
 
 
@@ -84,7 +84,7 @@ class SiteTable(BaseTable):
     class Meta(BaseTable.Meta):
         model = Site
         fields = (
-            'pk', 'name', 'slug', 'status', 'facility', 'region', 'group', 'tenant', 'asn', 'time_zone', 'description',
+            'pk', 'id', 'name', 'slug', 'status', 'facility', 'region', 'group', 'tenant', 'asn', 'time_zone', 'description',
             'physical_address', 'shipping_address', 'latitude', 'longitude', 'contact_name', 'contact_phone',
             'contact_email', 'comments', 'tags',
         )
@@ -120,5 +120,5 @@ class LocationTable(BaseTable):
 
     class Meta(BaseTable.Meta):
         model = Location
-        fields = ('pk', 'name', 'site', 'rack_count', 'device_count', 'description', 'slug', 'actions')
+        fields = ('pk', 'id', 'name', 'site', 'rack_count', 'device_count', 'description', 'slug', 'actions')
         default_columns = ('pk', 'name', 'site', 'rack_count', 'device_count', 'description', 'actions')
diff --git a/netbox/extras/tables.py b/netbox/extras/tables.py
index 20a6ffd8acd..63b3748c8aa 100644
--- a/netbox/extras/tables.py
+++ b/netbox/extras/tables.py
@@ -57,8 +57,8 @@ class CustomFieldTable(BaseTable):
     class Meta(BaseTable.Meta):
         model = CustomField
         fields = (
-            'pk', 'name', 'content_types', 'label', 'type', 'required', 'weight', 'default', 'description',
-            'filter_logic', 'choices',
+            'pk', 'id', 'name', 'content_types', 'label', 'type', 'required', 'weight', 'default',
+            'description', 'filter_logic', 'choices',
         )
         default_columns = ('pk', 'name', 'content_types', 'label', 'type', 'required', 'description')
 
@@ -78,7 +78,8 @@ class CustomLinkTable(BaseTable):
     class Meta(BaseTable.Meta):
         model = CustomLink
         fields = (
-            'pk', 'name', 'content_type', 'link_text', 'link_url', 'weight', 'group_name', 'button_class', 'new_window',
+            'pk', 'id', 'name', 'content_type', 'link_text', 'link_url', 'weight', 'group_name',
+            'button_class', 'new_window',
         )
         default_columns = ('pk', 'name', 'content_type', 'group_name', 'button_class', 'new_window')
 
@@ -98,7 +99,7 @@ class ExportTemplateTable(BaseTable):
     class Meta(BaseTable.Meta):
         model = ExportTemplate
         fields = (
-            'pk', 'name', 'content_type', 'description', 'mime_type', 'file_extension', 'as_attachment',
+            'pk', 'id', 'name', 'content_type', 'description', 'mime_type', 'file_extension', 'as_attachment',
         )
         default_columns = (
             'pk', 'name', 'content_type', 'description', 'mime_type', 'file_extension', 'as_attachment',
@@ -132,7 +133,7 @@ class WebhookTable(BaseTable):
     class Meta(BaseTable.Meta):
         model = Webhook
         fields = (
-            'pk', 'name', 'content_types', 'enabled', 'type_create', 'type_update', 'type_delete', 'http_method',
+            'pk', 'id', 'name', 'content_types', 'enabled', 'type_create', 'type_update', 'type_delete', 'http_method',
             'payload_url', 'secret', 'ssl_validation', 'ca_file_path',
         )
         default_columns = (
@@ -155,7 +156,8 @@ class TagTable(BaseTable):
 
     class Meta(BaseTable.Meta):
         model = Tag
-        fields = ('pk', 'name', 'items', 'slug', 'color', 'description', 'actions')
+        fields = ('pk', 'id', 'name', 'items', 'slug', 'color', 'description', 'actions')
+        default_columns = ('pk', 'name', 'items', 'slug', 'color', 'description', 'actions')
 
 
 class TaggedItemTable(BaseTable):
@@ -171,6 +173,7 @@ class TaggedItemTable(BaseTable):
     class Meta(BaseTable.Meta):
         model = TaggedItem
         fields = ('content_type', 'content_object')
+        exclude = ('id', )
 
 
 class ConfigContextTable(BaseTable):
@@ -185,8 +188,8 @@ class ConfigContextTable(BaseTable):
     class Meta(BaseTable.Meta):
         model = ConfigContext
         fields = (
-            'pk', 'name', 'weight', 'is_active', 'description', 'regions', 'sites', 'roles', 'platforms',
-            'cluster_groups', 'clusters', 'tenant_groups', 'tenants',
+            'pk', 'id', 'name', 'weight', 'is_active', 'description', 'regions', 'sites', 'roles',
+            'platforms', 'cluster_groups', 'clusters', 'tenant_groups', 'tenants',
         )
         default_columns = ('pk', 'name', 'weight', 'is_active', 'description')
 
@@ -211,7 +214,7 @@ class ObjectChangeTable(BaseTable):
 
     class Meta(BaseTable.Meta):
         model = ObjectChange
-        fields = ('time', 'user_name', 'action', 'changed_object_type', 'object_repr', 'request_id')
+        fields = ('id', 'time', 'user_name', 'action', 'changed_object_type', 'object_repr', 'request_id')
 
 
 class ObjectJournalTable(BaseTable):
@@ -232,7 +235,7 @@ class ObjectJournalTable(BaseTable):
 
     class Meta(BaseTable.Meta):
         model = JournalEntry
-        fields = ('created', 'created_by', 'kind', 'comments', 'actions')
+        fields = ('id', 'created', 'created_by', 'kind', 'comments', 'actions')
 
 
 class JournalEntryTable(ObjectJournalTable):
@@ -250,5 +253,10 @@ class JournalEntryTable(ObjectJournalTable):
     class Meta(BaseTable.Meta):
         model = JournalEntry
         fields = (
-            'pk', 'created', 'created_by', 'assigned_object_type', 'assigned_object', 'kind', 'comments', 'actions'
+            'pk', 'id', 'created', 'created_by', 'assigned_object_type', 'assigned_object', 'kind',
+            'comments', 'actions'
+        )
+        default_columns = (
+            'pk', 'created', 'created_by', 'assigned_object_type', 'assigned_object', 'kind',
+            'comments', 'actions'
         )
diff --git a/netbox/ipam/tables/ip.py b/netbox/ipam/tables/ip.py
index ddad6c57340..84ce7dd8a12 100644
--- a/netbox/ipam/tables/ip.py
+++ b/netbox/ipam/tables/ip.py
@@ -89,7 +89,7 @@ class RIRTable(BaseTable):
 
     class Meta(BaseTable.Meta):
         model = RIR
-        fields = ('pk', 'name', 'slug', 'is_private', 'aggregate_count', 'description', 'actions')
+        fields = ('pk', 'id', 'name', 'slug', 'is_private', 'aggregate_count', 'description', 'actions')
         default_columns = ('pk', 'name', 'is_private', 'aggregate_count', 'description', 'actions')
 
 
@@ -121,7 +121,7 @@ class AggregateTable(BaseTable):
 
     class Meta(BaseTable.Meta):
         model = Aggregate
-        fields = ('pk', 'prefix', 'rir', 'tenant', 'child_count', 'utilization', 'date_added', 'description', 'tags')
+        fields = ('pk', 'id', 'prefix', 'rir', 'tenant', 'child_count', 'utilization', 'date_added', 'description', 'tags')
         default_columns = ('pk', 'prefix', 'rir', 'tenant', 'child_count', 'utilization', 'date_added', 'description')
 
 
@@ -148,7 +148,7 @@ class RoleTable(BaseTable):
 
     class Meta(BaseTable.Meta):
         model = Role
-        fields = ('pk', 'name', 'slug', 'prefix_count', 'vlan_count', 'description', 'weight', 'actions')
+        fields = ('pk', 'id', 'name', 'slug', 'prefix_count', 'vlan_count', 'description', 'weight', 'actions')
         default_columns = ('pk', 'name', 'prefix_count', 'vlan_count', 'description', 'actions')
 
 
@@ -230,7 +230,7 @@ class PrefixTable(BaseTable):
     class Meta(BaseTable.Meta):
         model = Prefix
         fields = (
-            'pk', 'prefix', 'prefix_flat', 'status', 'children', 'vrf', 'utilization', 'tenant', 'site', 'vlan', 'role',
+            'pk', 'id', 'prefix', 'prefix_flat', 'status', 'children', 'vrf', 'utilization', 'tenant', 'site', 'vlan', 'role',
             'is_pool', 'mark_utilized', 'description', 'tags',
         )
         default_columns = (
@@ -268,7 +268,7 @@ class IPRangeTable(BaseTable):
     class Meta(BaseTable.Meta):
         model = IPRange
         fields = (
-            'pk', 'start_address', 'end_address', 'size', 'vrf', 'status', 'role', 'tenant', 'description',
+            'pk', 'id', 'start_address', 'end_address', 'size', 'vrf', 'status', 'role', 'tenant', 'description',
             'utilization',
         )
         default_columns = (
@@ -326,7 +326,7 @@ class IPAddressTable(BaseTable):
     class Meta(BaseTable.Meta):
         model = IPAddress
         fields = (
-            'pk', 'address', 'vrf', 'status', 'role', 'tenant', 'nat_inside', 'assigned', 'dns_name', 'description',
+            'pk', 'id', 'address', 'vrf', 'status', 'role', 'tenant', 'nat_inside', 'assigned', 'dns_name', 'description',
             'tags',
         )
         default_columns = (
@@ -350,6 +350,7 @@ class IPAddressAssignTable(BaseTable):
     class Meta(BaseTable.Meta):
         model = IPAddress
         fields = ('address', 'dns_name', 'vrf', 'status', 'role', 'tenant', 'assigned_object', 'description')
+        exclude = ('id', )
         orderable = False
 
 
@@ -374,3 +375,4 @@ class InterfaceIPAddressTable(BaseTable):
     class Meta(BaseTable.Meta):
         model = IPAddress
         fields = ('address', 'vrf', 'status', 'role', 'tenant', 'description')
+        exclude = ('id', )
diff --git a/netbox/ipam/tables/services.py b/netbox/ipam/tables/services.py
index 58c8ea49e61..ff6b766f7a9 100644
--- a/netbox/ipam/tables/services.py
+++ b/netbox/ipam/tables/services.py
@@ -31,5 +31,5 @@ class ServiceTable(BaseTable):
 
     class Meta(BaseTable.Meta):
         model = Service
-        fields = ('pk', 'name', 'parent', 'protocol', 'ports', 'ipaddresses', 'description', 'tags')
+        fields = ('pk', 'id', 'name', 'parent', 'protocol', 'ports', 'ipaddresses', 'description', 'tags')
         default_columns = ('pk', 'name', 'parent', 'protocol', 'ports', 'description')
diff --git a/netbox/ipam/tables/vlans.py b/netbox/ipam/tables/vlans.py
index fd1e92be8a0..84b250f872c 100644
--- a/netbox/ipam/tables/vlans.py
+++ b/netbox/ipam/tables/vlans.py
@@ -81,7 +81,7 @@ class VLANGroupTable(BaseTable):
 
     class Meta(BaseTable.Meta):
         model = VLANGroup
-        fields = ('pk', 'name', 'scope_type', 'scope', 'vlan_count', 'slug', 'description', 'actions')
+        fields = ('pk', 'id', 'name', 'scope_type', 'scope', 'vlan_count', 'slug', 'description', 'actions')
         default_columns = ('pk', 'name', 'scope_type', 'scope', 'vlan_count', 'description', 'actions')
 
 
@@ -119,7 +119,7 @@ class VLANTable(BaseTable):
 
     class Meta(BaseTable.Meta):
         model = VLAN
-        fields = ('pk', 'vid', 'name', 'site', 'group', 'prefixes', 'tenant', 'status', 'role', 'description', 'tags')
+        fields = ('pk', 'id', 'vid', 'name', 'site', 'group', 'prefixes', 'tenant', 'status', 'role', 'description', 'tags')
         default_columns = ('pk', 'vid', 'name', 'site', 'group', 'prefixes', 'tenant', 'status', 'role', 'description')
         row_attrs = {
             'class': lambda record: 'success' if not isinstance(record, VLAN) else '',
@@ -149,6 +149,7 @@ class VLANDevicesTable(VLANMembersTable):
     class Meta(BaseTable.Meta):
         model = Interface
         fields = ('device', 'name', 'tagged', 'actions')
+        exclude = ('id', )
 
 
 class VLANVirtualMachinesTable(VLANMembersTable):
@@ -160,6 +161,7 @@ class VLANVirtualMachinesTable(VLANMembersTable):
     class Meta(BaseTable.Meta):
         model = VMInterface
         fields = ('virtual_machine', 'name', 'tagged', 'actions')
+        exclude = ('id', )
 
 
 class InterfaceVLANTable(BaseTable):
@@ -187,6 +189,7 @@ class InterfaceVLANTable(BaseTable):
     class Meta(BaseTable.Meta):
         model = VLAN
         fields = ('vid', 'tagged', 'site', 'group', 'name', 'tenant', 'status', 'role', 'description')
+        exclude = ('id', )
 
     def __init__(self, interface, *args, **kwargs):
         self.interface = interface
diff --git a/netbox/ipam/tables/vrfs.py b/netbox/ipam/tables/vrfs.py
index 3a351a85616..1264368f464 100644
--- a/netbox/ipam/tables/vrfs.py
+++ b/netbox/ipam/tables/vrfs.py
@@ -47,7 +47,7 @@ class VRFTable(BaseTable):
     class Meta(BaseTable.Meta):
         model = VRF
         fields = (
-            'pk', 'name', 'rd', 'tenant', 'enforce_unique', 'description', 'import_targets', 'export_targets', 'tags',
+            'pk', 'id', 'name', 'rd', 'tenant', 'enforce_unique', 'description', 'import_targets', 'export_targets', 'tags',
         )
         default_columns = ('pk', 'name', 'rd', 'tenant', 'description')
 
@@ -68,5 +68,5 @@ class RouteTargetTable(BaseTable):
 
     class Meta(BaseTable.Meta):
         model = RouteTarget
-        fields = ('pk', 'name', 'tenant', 'description', 'tags')
+        fields = ('pk', 'id', 'name', 'tenant', 'description', 'tags')
         default_columns = ('pk', 'name', 'tenant', 'description')
diff --git a/netbox/tenancy/tables.py b/netbox/tenancy/tables.py
index f39ca1b18ad..a7bb087d85a 100644
--- a/netbox/tenancy/tables.py
+++ b/netbox/tenancy/tables.py
@@ -55,7 +55,7 @@ class TenantGroupTable(BaseTable):
 
     class Meta(BaseTable.Meta):
         model = TenantGroup
-        fields = ('pk', 'name', 'tenant_count', 'description', 'slug', 'actions')
+        fields = ('pk', 'id', 'name', 'tenant_count', 'description', 'slug', 'actions')
         default_columns = ('pk', 'name', 'tenant_count', 'description', 'actions')
 
 
@@ -78,5 +78,5 @@ class TenantTable(BaseTable):
 
     class Meta(BaseTable.Meta):
         model = Tenant
-        fields = ('pk', 'name', 'slug', 'group', 'description', 'comments', 'tags')
+        fields = ('pk', 'id', 'name', 'slug', 'group', 'description', 'comments', 'tags')
         default_columns = ('pk', 'name', 'group', 'description')
diff --git a/netbox/utilities/tables.py b/netbox/utilities/tables.py
index 42c9ffb5670..8258bd5e8e8 100644
--- a/netbox/utilities/tables.py
+++ b/netbox/utilities/tables.py
@@ -133,6 +133,11 @@ def objects_count(self):
             self._objects_count = sum(1 for obj in self.data if hasattr(obj, 'pk'))
         return self._objects_count
 
+    id = tables.Column(
+        linkify=True,
+        verbose_name='ID'
+    )
+
 
 #
 # Table columns
diff --git a/netbox/virtualization/tables.py b/netbox/virtualization/tables.py
index b0e922e71b8..cb6e6404380 100644
--- a/netbox/virtualization/tables.py
+++ b/netbox/virtualization/tables.py
@@ -44,7 +44,7 @@ class ClusterTypeTable(BaseTable):
 
     class Meta(BaseTable.Meta):
         model = ClusterType
-        fields = ('pk', 'name', 'slug', 'cluster_count', 'description', 'actions')
+        fields = ('pk', 'id', 'name', 'slug', 'cluster_count', 'description', 'actions')
         default_columns = ('pk', 'name', 'cluster_count', 'description', 'actions')
 
 
@@ -64,7 +64,7 @@ class ClusterGroupTable(BaseTable):
 
     class Meta(BaseTable.Meta):
         model = ClusterGroup
-        fields = ('pk', 'name', 'slug', 'cluster_count', 'description', 'actions')
+        fields = ('pk', 'id', 'name', 'slug', 'cluster_count', 'description', 'actions')
         default_columns = ('pk', 'name', 'cluster_count', 'description', 'actions')
 
 
@@ -100,7 +100,7 @@ class ClusterTable(BaseTable):
 
     class Meta(BaseTable.Meta):
         model = Cluster
-        fields = ('pk', 'name', 'type', 'group', 'tenant', 'site', 'comments', 'device_count', 'vm_count', 'tags')
+        fields = ('pk', 'id', 'name', 'type', 'group', 'tenant', 'site', 'comments', 'device_count', 'vm_count', 'tags')
         default_columns = ('pk', 'name', 'type', 'group', 'tenant', 'site', 'device_count', 'vm_count')
 
 
@@ -140,7 +140,7 @@ class VirtualMachineTable(BaseTable):
     class Meta(BaseTable.Meta):
         model = VirtualMachine
         fields = (
-            'pk', 'name', 'status', 'cluster', 'role', 'tenant', 'platform', 'vcpus', 'memory', 'disk', 'primary_ip4',
+            'pk', 'id', 'name', 'status', 'cluster', 'role', 'tenant', 'platform', 'vcpus', 'memory', 'disk', 'primary_ip4',
             'primary_ip6', 'primary_ip', 'comments', 'tags',
         )
         default_columns = (
@@ -170,7 +170,7 @@ class VMInterfaceTable(BaseInterfaceTable):
     class Meta(BaseTable.Meta):
         model = VMInterface
         fields = (
-            'pk', 'name', 'virtual_machine', 'enabled', 'parent', 'mac_address', 'mtu', 'mode', 'description', 'tags',
+            'pk', 'id', 'name', 'virtual_machine', 'enabled', 'parent', 'mac_address', 'mtu', 'mode', 'description', 'tags',
             'ip_addresses', 'untagged_vlan', 'tagged_vlans',
         )
         default_columns = ('pk', 'name', 'virtual_machine', 'enabled', 'parent', 'description')
@@ -186,7 +186,7 @@ class VirtualMachineVMInterfaceTable(VMInterfaceTable):
     class Meta(BaseTable.Meta):
         model = VMInterface
         fields = (
-            'pk', 'name', 'enabled', 'mac_address', 'mtu', 'mode', 'description', 'tags', 'ip_addresses',
+            'pk', 'id', 'name', 'enabled', 'mac_address', 'mtu', 'mode', 'description', 'tags', 'ip_addresses',
             'untagged_vlan', 'tagged_vlans', 'actions',
         )
         default_columns = (


Code review comments:
diff_hunk: @@ -171,6 +173,7 @@ class TaggedItemTable(BaseTable):
     class Meta(BaseTable.Meta):
         model = TaggedItem
         fields = ('content_type', 'content_object')
+        exclude = ('id', )
path: netbox/extras/tables.py
text: @author:
Exclude the `id` column from the 'Tagged Objects' table in the Tag detail view. This contains objects from several different models, so ID isn't unique. It didn't seem to make sense to include it (subjective).

@user1:
Alternatively, you can create a custom field (or use a template field) and link to the appropriate objects view

@author:
Actually, I said that wrong. TaggedItem does have an ID for the TaggedItem object itself, which is not the same as the corresponding object's ID. The TaggedItem ID isn't useful information to expose, as I don't think that's accessible/usable anywhere?

I could make the ID column expose the object ID instead, but I wasn't sure how useful that is for a couple of reasons. 

1. this table isn't exportable, which is the primary reason this change was requested in the first place (though, the ID column is currently on plenty of other non-exportable table views, so that's kind of moot).
2. object ID isn't inherently unique in this table, so needs to be used in conjunction with the type column in order to extract useful information
3. If linkify-ing it, the object column is already linked to that object's detail page

Though, now that I actually look at it again, it's a lot easier to properly include the object ID and linkify it than I initially thought it would be, so this isn't really a big deal to add/get working after all.