diff --git a/netbox/dcim/tables/__init__.py b/netbox/dcim/tables/__init__.py index e68779e3d..8a861c8c2 100644 --- a/netbox/dcim/tables/__init__.py +++ b/netbox/dcim/tables/__init__.py @@ -40,8 +40,6 @@ class ConsoleConnectionTable(BaseTable): verbose_name='Reachable' ) - add_prefetch = False - class Meta(BaseTable.Meta): model = ConsolePort fields = ('device', 'name', 'console_server', 'console_server_port', 'reachable') @@ -72,8 +70,6 @@ class PowerConnectionTable(BaseTable): verbose_name='Reachable' ) - add_prefetch = False - class Meta(BaseTable.Meta): model = PowerPort fields = ('device', 'name', 'pdu', 'outlet', 'reachable') @@ -107,8 +103,6 @@ class InterfaceConnectionTable(BaseTable): verbose_name='Reachable' ) - add_prefetch = False - class Meta(BaseTable.Meta): model = Interface fields = ('device_a', 'interface_a', 'device_b', 'interface_b', 'reachable') diff --git a/netbox/ipam/tables.py b/netbox/ipam/tables.py index 0104077c0..bbca3f082 100644 --- a/netbox/ipam/tables.py +++ b/netbox/ipam/tables.py @@ -280,8 +280,6 @@ class PrefixTable(BaseTable): verbose_name='Pool' ) - add_prefetch = False - class Meta(BaseTable.Meta): model = Prefix fields = ( diff --git a/netbox/utilities/tables.py b/netbox/utilities/tables.py index 4f5c4508a..58c9b4499 100644 --- a/netbox/utilities/tables.py +++ b/netbox/utilities/tables.py @@ -14,11 +14,6 @@ class BaseTable(tables.Table): :param user: Personalize table display for the given user (optional). Has no effect if AnonymousUser is passed. """ - # By default, modify the queryset passed to the table upon initialization to automatically prefetch related - # data. Set this to False if it's necessary to avoid modifying the queryset (e.g. to accommodate - # PrefixQuerySet.annotate_depth()). - add_prefetch = True - class Meta: attrs = { 'class': 'table table-hover table-headings', @@ -61,18 +56,28 @@ class BaseTable(tables.Table): self.sequence.append('actions') # Dynamically update the table's QuerySet to ensure related fields are pre-fetched - if self.add_prefetch and isinstance(self.data, TableQuerysetData): - model = getattr(self.Meta, 'model') + if isinstance(self.data, TableQuerysetData): prefetch_fields = [] for column in self.columns: if column.visible: - field_path = column.accessor.split('.') - try: - model_field = model._meta.get_field(field_path[0]) - if isinstance(model_field, (RelatedField, GenericForeignKey)): - prefetch_fields.append('__'.join(field_path)) - except FieldDoesNotExist: - pass + model = getattr(self.Meta, 'model') + accessor = column.accessor + prefetch_path = [] + for field_name in accessor.split(accessor.SEPARATOR): + try: + field = model._meta.get_field(field_name) + except FieldDoesNotExist: + break + if isinstance(field, RelatedField): + # Follow ForeignKeys to the related model + prefetch_path.append(field_name) + model = field.remote_field.model + elif isinstance(field, GenericForeignKey): + # Can't prefetch beyond a GenericForeignKey + prefetch_path.append(field_name) + break + if prefetch_path: + prefetch_fields.append('__'.join(prefetch_path)) self.data.data = self.data.data.prefetch_related(None).prefetch_related(*prefetch_fields) @property