Przeglądaj źródła

Closes #6954: Remember users' table ordering preferences

jeremystretch 4 lat temu
rodzic
commit
21e0e6e495

+ 7 - 6
docs/development/user-preferences.md

@@ -4,9 +4,10 @@ The `users.UserConfig` model holds individual preferences for each user in the f
 
 
 ## Available Preferences
 ## Available Preferences
 
 
-| Name                    | Description |
-|-------------------------|-------------|
-| data_format             | Preferred format when rendering raw data (JSON or YAML) |
-| pagination.per_page     | The number of items to display per page of a paginated table |
-| tables.${table}.columns | The ordered list of columns to display when viewing the table |
-| ui.colormode            | Light or dark mode in the user interface |
+| Name                     | Description                                                   |
+|--------------------------|---------------------------------------------------------------|
+| data_format              | Preferred format when rendering raw data (JSON or YAML)       |
+| pagination.per_page      | The number of items to display per page of a paginated table  |
+| tables.${table}.columns  | The ordered list of columns to display when viewing the table |
+| tables.${table}.ordering | A list of column names by which the table should be ordered   |
+| ui.colormode             | Light or dark mode in the user interface                      |

+ 1 - 0
docs/release-notes/version-3.2.md

@@ -56,6 +56,7 @@ Inventory item templates can be arranged hierarchically within a device type, an
 
 
 ### Enhancements
 ### Enhancements
 
 
+* [#6954](https://github.com/netbox-community/netbox/issues/6954) - Remember users' table ordering preferences
 * [#7650](https://github.com/netbox-community/netbox/issues/7650) - Add support for local account password validation
 * [#7650](https://github.com/netbox-community/netbox/issues/7650) - Add support for local account password validation
 * [#7679](https://github.com/netbox-community/netbox/issues/7679) - Add actions menu to all object tables
 * [#7679](https://github.com/netbox-community/netbox/issues/7679) - Add actions menu to all object tables
 * [#7681](https://github.com/netbox-community/netbox/issues/7681) - Add `service_id` field for provider networks
 * [#7681](https://github.com/netbox-community/netbox/issues/7681) - Add `service_id` field for provider networks

+ 4 - 4
netbox/circuits/views.py

@@ -5,7 +5,7 @@ from django.shortcuts import get_object_or_404, redirect, render
 
 
 from netbox.views import generic
 from netbox.views import generic
 from utilities.forms import ConfirmationForm
 from utilities.forms import ConfirmationForm
-from utilities.tables import paginate_table
+from utilities.tables import configure_table
 from utilities.utils import count_related
 from utilities.utils import count_related
 from . import filtersets, forms, tables
 from . import filtersets, forms, tables
 from .choices import CircuitTerminationSideChoices
 from .choices import CircuitTerminationSideChoices
@@ -35,7 +35,7 @@ class ProviderView(generic.ObjectView):
             'type', 'tenant', 'terminations__site'
             'type', 'tenant', 'terminations__site'
         )
         )
         circuits_table = tables.CircuitTable(circuits, exclude=('provider',))
         circuits_table = tables.CircuitTable(circuits, exclude=('provider',))
-        paginate_table(circuits_table, request)
+        configure_table(circuits_table, request)
 
 
         return {
         return {
             'circuits_table': circuits_table,
             'circuits_table': circuits_table,
@@ -96,7 +96,7 @@ class ProviderNetworkView(generic.ObjectView):
             'type', 'tenant', 'terminations__site'
             'type', 'tenant', 'terminations__site'
         )
         )
         circuits_table = tables.CircuitTable(circuits)
         circuits_table = tables.CircuitTable(circuits)
-        paginate_table(circuits_table, request)
+        configure_table(circuits_table, request)
 
 
         return {
         return {
             'circuits_table': circuits_table,
             'circuits_table': circuits_table,
@@ -150,7 +150,7 @@ class CircuitTypeView(generic.ObjectView):
     def get_extra_context(self, request, instance):
     def get_extra_context(self, request, instance):
         circuits = Circuit.objects.restrict(request.user, 'view').filter(type=instance)
         circuits = Circuit.objects.restrict(request.user, 'view').filter(type=instance)
         circuits_table = tables.CircuitTable(circuits, exclude=('type',))
         circuits_table = tables.CircuitTable(circuits, exclude=('type',))
-        paginate_table(circuits_table, request)
+        configure_table(circuits_table, request)
 
 
         return {
         return {
             'circuits_table': circuits_table,
             'circuits_table': circuits_table,

+ 8 - 8
netbox/dcim/views.py

@@ -20,7 +20,7 @@ from netbox.views import generic
 from utilities.forms import ConfirmationForm
 from utilities.forms import ConfirmationForm
 from utilities.paginator import EnhancedPaginator, get_paginate_count
 from utilities.paginator import EnhancedPaginator, get_paginate_count
 from utilities.permissions import get_permission_for_model
 from utilities.permissions import get_permission_for_model
-from utilities.tables import paginate_table
+from utilities.tables import configure_table
 from utilities.utils import count_related
 from utilities.utils import count_related
 from utilities.views import GetReturnURLMixin, ObjectPermissionRequiredMixin
 from utilities.views import GetReturnURLMixin, ObjectPermissionRequiredMixin
 from virtualization.models import VirtualMachine
 from virtualization.models import VirtualMachine
@@ -165,7 +165,7 @@ class RegionView(generic.ObjectView):
             region=instance
             region=instance
         )
         )
         sites_table = tables.SiteTable(sites, exclude=('region',))
         sites_table = tables.SiteTable(sites, exclude=('region',))
-        paginate_table(sites_table, request)
+        configure_table(sites_table, request)
 
 
         return {
         return {
             'child_regions_table': child_regions_table,
             'child_regions_table': child_regions_table,
@@ -250,7 +250,7 @@ class SiteGroupView(generic.ObjectView):
             group=instance
             group=instance
         )
         )
         sites_table = tables.SiteTable(sites, exclude=('group',))
         sites_table = tables.SiteTable(sites, exclude=('group',))
-        paginate_table(sites_table, request)
+        configure_table(sites_table, request)
 
 
         return {
         return {
             'child_groups_table': child_groups_table,
             'child_groups_table': child_groups_table,
@@ -422,7 +422,7 @@ class LocationView(generic.ObjectView):
             cumulative=True
             cumulative=True
         ).filter(pk__in=location_ids).exclude(pk=instance.pk)
         ).filter(pk__in=location_ids).exclude(pk=instance.pk)
         child_locations_table = tables.LocationTable(child_locations)
         child_locations_table = tables.LocationTable(child_locations)
-        paginate_table(child_locations_table, request)
+        configure_table(child_locations_table, request)
 
 
         return {
         return {
             'rack_count': rack_count,
             'rack_count': rack_count,
@@ -493,7 +493,7 @@ class RackRoleView(generic.ObjectView):
         )
         )
 
 
         racks_table = tables.RackTable(racks, exclude=('role', 'get_utilization', 'get_power_utilization'))
         racks_table = tables.RackTable(racks, exclude=('role', 'get_utilization', 'get_power_utilization'))
-        paginate_table(racks_table, request)
+        configure_table(racks_table, request)
 
 
         return {
         return {
             'racks_table': racks_table,
             'racks_table': racks_table,
@@ -743,7 +743,7 @@ class ManufacturerView(generic.ObjectView):
         )
         )
 
 
         devicetypes_table = tables.DeviceTypeTable(devicetypes, exclude=('manufacturer',))
         devicetypes_table = tables.DeviceTypeTable(devicetypes, exclude=('manufacturer',))
-        paginate_table(devicetypes_table, request)
+        configure_table(devicetypes_table, request)
 
 
         return {
         return {
             'devicetypes_table': devicetypes_table,
             'devicetypes_table': devicetypes_table,
@@ -1439,7 +1439,7 @@ class DeviceRoleView(generic.ObjectView):
             device_role=instance
             device_role=instance
         )
         )
         devices_table = tables.DeviceTable(devices, exclude=('device_role',))
         devices_table = tables.DeviceTable(devices, exclude=('device_role',))
-        paginate_table(devices_table, request)
+        configure_table(devices_table, request)
 
 
         return {
         return {
             'devices_table': devices_table,
             'devices_table': devices_table,
@@ -1503,7 +1503,7 @@ class PlatformView(generic.ObjectView):
             platform=instance
             platform=instance
         )
         )
         devices_table = tables.DeviceTable(devices, exclude=('platform',))
         devices_table = tables.DeviceTable(devices, exclude=('platform',))
-        paginate_table(devices_table, request)
+        configure_table(devices_table, request)
 
 
         return {
         return {
             'devices_table': devices_table,
             'devices_table': devices_table,

+ 4 - 4
netbox/extras/views.py

@@ -11,7 +11,7 @@ from rq import Worker
 from netbox.views import generic
 from netbox.views import generic
 from utilities.forms import ConfirmationForm
 from utilities.forms import ConfirmationForm
 from utilities.htmx import is_htmx
 from utilities.htmx import is_htmx
-from utilities.tables import paginate_table
+from utilities.tables import configure_table
 from utilities.utils import copy_safe_request, count_related, normalize_querydict, shallow_compare_dict
 from utilities.utils import copy_safe_request, count_related, normalize_querydict, shallow_compare_dict
 from utilities.views import ContentTypePermissionRequiredMixin
 from utilities.views import ContentTypePermissionRequiredMixin
 from . import filtersets, forms, tables
 from . import filtersets, forms, tables
@@ -215,7 +215,7 @@ class TagView(generic.ObjectView):
             data=tagged_items,
             data=tagged_items,
             orderable=False
             orderable=False
         )
         )
-        paginate_table(taggeditem_table, request)
+        configure_table(taggeditem_table, request)
 
 
         object_types = [
         object_types = [
             {
             {
@@ -451,7 +451,7 @@ class ObjectChangeLogView(View):
             data=objectchanges,
             data=objectchanges,
             orderable=False
             orderable=False
         )
         )
-        paginate_table(objectchanges_table, request)
+        configure_table(objectchanges_table, request)
 
 
         # Default to using "<app>/<model>.html" as the template, if it exists. Otherwise,
         # Default to using "<app>/<model>.html" as the template, if it exists. Otherwise,
         # fall back to using base.html.
         # fall back to using base.html.
@@ -571,7 +571,7 @@ class ObjectJournalView(View):
             assigned_object_id=obj.pk
             assigned_object_id=obj.pk
         )
         )
         journalentry_table = tables.ObjectJournalTable(journalentries)
         journalentry_table = tables.ObjectJournalTable(journalentries)
-        paginate_table(journalentry_table, request)
+        configure_table(journalentry_table, request)
 
 
         if request.user.has_perm('extras.add_journalentry'):
         if request.user.has_perm('extras.add_journalentry'):
             form = forms.JournalEntryForm(
             form = forms.JournalEntryForm(

+ 6 - 6
netbox/ipam/views.py

@@ -8,7 +8,7 @@ from dcim.filtersets import InterfaceFilterSet
 from dcim.models import Interface, Site
 from dcim.models import Interface, Site
 from dcim.tables import SiteTable
 from dcim.tables import SiteTable
 from netbox.views import generic
 from netbox.views import generic
-from utilities.tables import paginate_table
+from utilities.tables import configure_table
 from utilities.utils import count_related
 from utilities.utils import count_related
 from virtualization.filtersets import VMInterfaceFilterSet
 from virtualization.filtersets import VMInterfaceFilterSet
 from virtualization.models import VMInterface
 from virtualization.models import VMInterface
@@ -161,7 +161,7 @@ class RIRView(generic.ObjectView):
             rir=instance
             rir=instance
         )
         )
         aggregates_table = tables.AggregateTable(aggregates, exclude=('rir', 'utilization'))
         aggregates_table = tables.AggregateTable(aggregates, exclude=('rir', 'utilization'))
-        paginate_table(aggregates_table, request)
+        configure_table(aggregates_table, request)
 
 
         return {
         return {
             'aggregates_table': aggregates_table,
             'aggregates_table': aggregates_table,
@@ -219,7 +219,7 @@ class ASNView(generic.ObjectView):
     def get_extra_context(self, request, instance):
     def get_extra_context(self, request, instance):
         sites = instance.sites.restrict(request.user, 'view')
         sites = instance.sites.restrict(request.user, 'view')
         sites_table = SiteTable(sites)
         sites_table = SiteTable(sites)
-        paginate_table(sites_table, request)
+        configure_table(sites_table, request)
 
 
         return {
         return {
             'sites_table': sites_table,
             'sites_table': sites_table,
@@ -356,7 +356,7 @@ class RoleView(generic.ObjectView):
         )
         )
 
 
         prefixes_table = tables.PrefixTable(prefixes, exclude=('role', 'utilization'))
         prefixes_table = tables.PrefixTable(prefixes, exclude=('role', 'utilization'))
-        paginate_table(prefixes_table, request)
+        configure_table(prefixes_table, request)
 
 
         return {
         return {
             'prefixes_table': prefixes_table,
             'prefixes_table': prefixes_table,
@@ -664,7 +664,7 @@ class IPAddressView(generic.ObjectView):
             vrf=instance.vrf, address__net_contained_or_equal=str(instance.address)
             vrf=instance.vrf, address__net_contained_or_equal=str(instance.address)
         )
         )
         related_ips_table = tables.IPAddressTable(related_ips, orderable=False)
         related_ips_table = tables.IPAddressTable(related_ips, orderable=False)
-        paginate_table(related_ips_table, request)
+        configure_table(related_ips_table, request)
 
 
         return {
         return {
             'parent_prefixes_table': parent_prefixes_table,
             'parent_prefixes_table': parent_prefixes_table,
@@ -800,7 +800,7 @@ class VLANGroupView(generic.ObjectView):
         vlans_table = tables.VLANTable(vlans, exclude=('site', 'group', 'prefixes'))
         vlans_table = tables.VLANTable(vlans, exclude=('site', 'group', 'prefixes'))
         if request.user.has_perm('ipam.change_vlan') or request.user.has_perm('ipam.delete_vlan'):
         if request.user.has_perm('ipam.change_vlan') or request.user.has_perm('ipam.delete_vlan'):
             vlans_table.columns.show('pk')
             vlans_table.columns.show('pk')
-        paginate_table(vlans_table, request)
+        configure_table(vlans_table, request)
 
 
         # Compile permissions list for rendering the object table
         # Compile permissions list for rendering the object table
         permissions = {
         permissions = {

+ 3 - 4
netbox/netbox/views/generic/object_views.py

@@ -15,7 +15,6 @@ from django.utils.safestring import mark_safe
 from django.views.generic import View
 from django.views.generic import View
 from django_tables2.export import TableExport
 from django_tables2.export import TableExport
 
 
-from dcim.forms.object_create import ComponentCreateForm
 from extras.models import ExportTemplate
 from extras.models import ExportTemplate
 from extras.signals import clear_webhooks
 from extras.signals import clear_webhooks
 from utilities.error_handlers import handle_protectederror
 from utilities.error_handlers import handle_protectederror
@@ -23,7 +22,7 @@ from utilities.exceptions import AbortTransaction, PermissionsViolation
 from utilities.forms import ConfirmationForm, ImportForm, restrict_form_fields
 from utilities.forms import ConfirmationForm, ImportForm, restrict_form_fields
 from utilities.htmx import is_htmx
 from utilities.htmx import is_htmx
 from utilities.permissions import get_permission_for_model
 from utilities.permissions import get_permission_for_model
-from utilities.tables import paginate_table
+from utilities.tables import configure_table
 from utilities.utils import normalize_querydict, prepare_cloned_fields
 from utilities.utils import normalize_querydict, prepare_cloned_fields
 from utilities.views import GetReturnURLMixin, ObjectPermissionRequiredMixin
 from utilities.views import GetReturnURLMixin, ObjectPermissionRequiredMixin
 
 
@@ -135,7 +134,7 @@ class ObjectChildrenView(ObjectView):
         # Determine whether to display bulk action checkboxes
         # Determine whether to display bulk action checkboxes
         if 'pk' in table.base_columns and (permissions['change'] or permissions['delete']):
         if 'pk' in table.base_columns and (permissions['change'] or permissions['delete']):
             table.columns.show('pk')
             table.columns.show('pk')
-        paginate_table(table, request)
+        configure_table(table, request)
 
 
         # If this is an HTMX request, return only the rendered table HTML
         # If this is an HTMX request, return only the rendered table HTML
         if is_htmx(request):
         if is_htmx(request):
@@ -284,7 +283,7 @@ class ObjectListView(ObjectPermissionRequiredMixin, View):
 
 
         # Render the objects table
         # Render the objects table
         table = self.get_table(request, permissions)
         table = self.get_table(request, permissions)
-        paginate_table(table, request)
+        configure_table(table, request)
 
 
         # If this is an HTMX request, return only the rendered table HTML
         # If this is an HTMX request, return only the rendered table HTML
         if is_htmx(request):
         if is_htmx(request):

+ 5 - 5
netbox/tenancy/views.py

@@ -6,7 +6,7 @@ from circuits.models import Circuit
 from dcim.models import Site, Rack, Device, RackReservation
 from dcim.models import Site, Rack, Device, RackReservation
 from ipam.models import Aggregate, IPAddress, Prefix, VLAN, VRF
 from ipam.models import Aggregate, IPAddress, Prefix, VLAN, VRF
 from netbox.views import generic
 from netbox.views import generic
-from utilities.tables import paginate_table
+from utilities.tables import configure_table
 from utilities.utils import count_related
 from utilities.utils import count_related
 from virtualization.models import VirtualMachine, Cluster
 from virtualization.models import VirtualMachine, Cluster
 from . import filtersets, forms, tables
 from . import filtersets, forms, tables
@@ -38,7 +38,7 @@ class TenantGroupView(generic.ObjectView):
             group=instance
             group=instance
         )
         )
         tenants_table = tables.TenantTable(tenants, exclude=('group',))
         tenants_table = tables.TenantTable(tenants, exclude=('group',))
-        paginate_table(tenants_table, request)
+        configure_table(tenants_table, request)
 
 
         return {
         return {
             'tenants_table': tenants_table,
             'tenants_table': tenants_table,
@@ -184,7 +184,7 @@ class ContactGroupView(generic.ObjectView):
             group=instance
             group=instance
         )
         )
         contacts_table = tables.ContactTable(contacts, exclude=('group',))
         contacts_table = tables.ContactTable(contacts, exclude=('group',))
-        paginate_table(contacts_table, request)
+        configure_table(contacts_table, request)
 
 
         return {
         return {
             'child_groups_table': child_groups_table,
             'child_groups_table': child_groups_table,
@@ -251,7 +251,7 @@ class ContactRoleView(generic.ObjectView):
         )
         )
         contacts_table = tables.ContactAssignmentTable(contact_assignments)
         contacts_table = tables.ContactAssignmentTable(contact_assignments)
         contacts_table.columns.hide('role')
         contacts_table.columns.hide('role')
-        paginate_table(contacts_table, request)
+        configure_table(contacts_table, request)
 
 
         return {
         return {
             'contacts_table': contacts_table,
             'contacts_table': contacts_table,
@@ -308,7 +308,7 @@ class ContactView(generic.ObjectView):
         )
         )
         assignments_table = tables.ContactAssignmentTable(contact_assignments)
         assignments_table = tables.ContactAssignmentTable(contact_assignments)
         assignments_table.columns.hide('contact')
         assignments_table.columns.hide('contact')
-        paginate_table(assignments_table, request)
+        configure_table(assignments_table, request)
 
 
         return {
         return {
             'assignments_table': assignments_table,
             'assignments_table': assignments_table,

+ 26 - 1
netbox/users/tests/test_preferences.py

@@ -1,7 +1,13 @@
 from django.contrib.auth.models import User
 from django.contrib.auth.models import User
-from django.test import override_settings, TestCase
+from django.test import override_settings
+from django.test.client import RequestFactory
+from django.urls import reverse
 
 
+from dcim.models import Site
+from dcim.tables import SiteTable
 from users.preferences import UserPreference
 from users.preferences import UserPreference
+from utilities.tables import configure_table
+from utilities.testing import TestCase
 
 
 
 
 DEFAULT_USER_PREFERENCES = {
 DEFAULT_USER_PREFERENCES = {
@@ -12,6 +18,7 @@ DEFAULT_USER_PREFERENCES = {
 
 
 
 
 class UserPreferencesTest(TestCase):
 class UserPreferencesTest(TestCase):
+    user_permissions = ['dcim.view_site']
 
 
     def test_userpreference(self):
     def test_userpreference(self):
         CHOICES = (
         CHOICES = (
@@ -37,3 +44,21 @@ class UserPreferencesTest(TestCase):
         userconfig = user.config
         userconfig = user.config
 
 
         self.assertEqual(userconfig.data, DEFAULT_USER_PREFERENCES)
         self.assertEqual(userconfig.data, DEFAULT_USER_PREFERENCES)
+
+    def test_table_ordering(self):
+        url = reverse('dcim:site_list')
+        response = self.client.get(f"{url}?sort=status")
+        self.assertEqual(response.status_code, 200)
+
+        # Check that table ordering preference has been recorded
+        self.user.refresh_from_db()
+        ordering = self.user.config.get(f'tables.SiteTable.ordering')
+        self.assertEqual(ordering, ['status'])
+
+        # Check that a recorded preference is honored by default
+        self.user.config.set(f'tables.SiteTable.ordering', ['-status'], commit=True)
+        table = SiteTable(Site.objects.all())
+        request = RequestFactory().get(url)
+        request.user = self.user
+        configure_table(table, request)
+        self.assertEqual(table.order_by, ('-status',))

+ 14 - 5
netbox/utilities/tables/__init__.py

@@ -5,14 +5,23 @@ from .columns import *
 from .tables import *
 from .tables import *
 
 
 
 
-#
-# Pagination
-#
-
-def paginate_table(table, request):
+def configure_table(table, request):
     """
     """
     Paginate a table given a request context.
     Paginate a table given a request context.
     """
     """
+    # Save ordering preference
+    if request.user.is_authenticated:
+        table_name = table.__class__.__name__
+        if table.prefixed_order_by_field in request.GET:
+            # If an ordering has been specified as a query parameter, save it as the
+            # user's preferred ordering for this table.
+            ordering = request.GET.getlist(table.prefixed_order_by_field)
+            request.user.config.set(f'tables.{table_name}.ordering', ordering, commit=True)
+        elif ordering := request.user.config.get(f'tables.{table_name}.ordering'):
+            # If no ordering has been specified, set the preferred ordering (if any).
+            table.order_by = ordering
+
+    # Paginate the table results
     paginate = {
     paginate = {
         'paginator_class': EnhancedPaginator,
         'paginator_class': EnhancedPaginator,
         'per_page': get_paginate_count(request)
         'per_page': get_paginate_count(request)

+ 3 - 3
netbox/virtualization/views.py

@@ -11,7 +11,7 @@ from extras.views import ObjectConfigContextView
 from ipam.models import IPAddress, Service
 from ipam.models import IPAddress, Service
 from ipam.tables import AssignedIPAddressesTable, InterfaceVLANTable
 from ipam.tables import AssignedIPAddressesTable, InterfaceVLANTable
 from netbox.views import generic
 from netbox.views import generic
-from utilities.tables import paginate_table
+from utilities.tables import configure_table
 from utilities.utils import count_related
 from utilities.utils import count_related
 from . import filtersets, forms, tables
 from . import filtersets, forms, tables
 from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface
 from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface
@@ -41,7 +41,7 @@ class ClusterTypeView(generic.ObjectView):
             vm_count=count_related(VirtualMachine, 'cluster')
             vm_count=count_related(VirtualMachine, 'cluster')
         )
         )
         clusters_table = tables.ClusterTable(clusters, exclude=('type',))
         clusters_table = tables.ClusterTable(clusters, exclude=('type',))
-        paginate_table(clusters_table, request)
+        configure_table(clusters_table, request)
 
 
         return {
         return {
             'clusters_table': clusters_table,
             'clusters_table': clusters_table,
@@ -103,7 +103,7 @@ class ClusterGroupView(generic.ObjectView):
             vm_count=count_related(VirtualMachine, 'cluster')
             vm_count=count_related(VirtualMachine, 'cluster')
         )
         )
         clusters_table = tables.ClusterTable(clusters, exclude=('group',))
         clusters_table = tables.ClusterTable(clusters, exclude=('group',))
-        paginate_table(clusters_table, request)
+        configure_table(clusters_table, request)
 
 
         return {
         return {
             'clusters_table': clusters_table,
             'clusters_table': clusters_table,

+ 3 - 3
netbox/wireless/views.py

@@ -1,6 +1,6 @@
 from dcim.models import Interface
 from dcim.models import Interface
 from netbox.views import generic
 from netbox.views import generic
-from utilities.tables import paginate_table
+from utilities.tables import configure_table
 from utilities.utils import count_related
 from utilities.utils import count_related
 from . import filtersets, forms, tables
 from . import filtersets, forms, tables
 from .models import *
 from .models import *
@@ -31,7 +31,7 @@ class WirelessLANGroupView(generic.ObjectView):
             group=instance
             group=instance
         )
         )
         wirelesslans_table = tables.WirelessLANTable(wirelesslans, exclude=('group',))
         wirelesslans_table = tables.WirelessLANTable(wirelesslans, exclude=('group',))
-        paginate_table(wirelesslans_table, request)
+        configure_table(wirelesslans_table, request)
 
 
         return {
         return {
             'wirelesslans_table': wirelesslans_table,
             'wirelesslans_table': wirelesslans_table,
@@ -99,7 +99,7 @@ class WirelessLANView(generic.ObjectView):
             wireless_lans=instance
             wireless_lans=instance
         )
         )
         interfaces_table = tables.WirelessLANInterfacesTable(attached_interfaces)
         interfaces_table = tables.WirelessLANInterfacesTable(attached_interfaces)
-        paginate_table(interfaces_table, request)
+        configure_table(interfaces_table, request)
 
 
         return {
         return {
             'interfaces_table': interfaces_table,
             'interfaces_table': interfaces_table,