mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Move configure_table() logic to NetBoxTable.configure()
This commit is contained in:
@ -35,3 +35,14 @@ class MyModelTable(NetBoxTable):
|
||||
fields = ('pk', 'id', 'name', ...)
|
||||
default_columns = ('pk', 'name', ...)
|
||||
```
|
||||
|
||||
### Table Configuration
|
||||
|
||||
The NetBoxTable class supports dynamic configuration to support pagination and to effect user preferences. To configure a table for a specific request, simply call its `configure()` method and pass the current HTTPRequest object. For example:
|
||||
|
||||
```python
|
||||
table = MyModelTable(data=MyModel.objects.all())
|
||||
table.configure(request)
|
||||
```
|
||||
|
||||
If using a generic view provided by NetBox, table configuration is handled automatically.
|
||||
|
@ -5,7 +5,6 @@ from django.shortcuts import get_object_or_404, redirect, render
|
||||
|
||||
from netbox.views import generic
|
||||
from utilities.forms import ConfirmationForm
|
||||
from netbox.tables import configure_table
|
||||
from utilities.utils import count_related
|
||||
from . import filtersets, forms, tables
|
||||
from .models import *
|
||||
@ -34,7 +33,7 @@ class ProviderView(generic.ObjectView):
|
||||
'type', 'tenant', 'terminations__site'
|
||||
)
|
||||
circuits_table = tables.CircuitTable(circuits, exclude=('provider',))
|
||||
configure_table(circuits_table, request)
|
||||
circuits_table.configure(request)
|
||||
|
||||
return {
|
||||
'circuits_table': circuits_table,
|
||||
@ -95,7 +94,7 @@ class ProviderNetworkView(generic.ObjectView):
|
||||
'type', 'tenant', 'terminations__site'
|
||||
)
|
||||
circuits_table = tables.CircuitTable(circuits)
|
||||
configure_table(circuits_table, request)
|
||||
circuits_table.configure(request)
|
||||
|
||||
return {
|
||||
'circuits_table': circuits_table,
|
||||
@ -149,7 +148,7 @@ class CircuitTypeView(generic.ObjectView):
|
||||
def get_extra_context(self, request, instance):
|
||||
circuits = Circuit.objects.restrict(request.user, 'view').filter(type=instance)
|
||||
circuits_table = tables.CircuitTable(circuits, exclude=('type',))
|
||||
configure_table(circuits_table, request)
|
||||
circuits_table.configure(request)
|
||||
|
||||
return {
|
||||
'circuits_table': circuits_table,
|
||||
|
@ -20,7 +20,6 @@ from netbox.views import generic
|
||||
from utilities.forms import ConfirmationForm
|
||||
from utilities.paginator import EnhancedPaginator, get_paginate_count
|
||||
from utilities.permissions import get_permission_for_model
|
||||
from netbox.tables import configure_table
|
||||
from utilities.utils import count_related
|
||||
from utilities.views import GetReturnURLMixin, ObjectPermissionRequiredMixin
|
||||
from virtualization.models import VirtualMachine
|
||||
@ -165,7 +164,7 @@ class RegionView(generic.ObjectView):
|
||||
region=instance
|
||||
)
|
||||
sites_table = tables.SiteTable(sites, exclude=('region',))
|
||||
configure_table(sites_table, request)
|
||||
sites_table.configure(request)
|
||||
|
||||
return {
|
||||
'child_regions_table': child_regions_table,
|
||||
@ -250,7 +249,7 @@ class SiteGroupView(generic.ObjectView):
|
||||
group=instance
|
||||
)
|
||||
sites_table = tables.SiteTable(sites, exclude=('group',))
|
||||
configure_table(sites_table, request)
|
||||
sites_table.configure(request)
|
||||
|
||||
return {
|
||||
'child_groups_table': child_groups_table,
|
||||
@ -422,7 +421,7 @@ class LocationView(generic.ObjectView):
|
||||
cumulative=True
|
||||
).filter(pk__in=location_ids).exclude(pk=instance.pk)
|
||||
child_locations_table = tables.LocationTable(child_locations)
|
||||
configure_table(child_locations_table, request)
|
||||
child_locations_table.configure(request)
|
||||
|
||||
return {
|
||||
'rack_count': rack_count,
|
||||
@ -493,7 +492,7 @@ class RackRoleView(generic.ObjectView):
|
||||
)
|
||||
|
||||
racks_table = tables.RackTable(racks, exclude=('role', 'get_utilization', 'get_power_utilization'))
|
||||
configure_table(racks_table, request)
|
||||
racks_table.configure(request)
|
||||
|
||||
return {
|
||||
'racks_table': racks_table,
|
||||
@ -743,7 +742,7 @@ class ManufacturerView(generic.ObjectView):
|
||||
)
|
||||
|
||||
devicetypes_table = tables.DeviceTypeTable(devicetypes, exclude=('manufacturer',))
|
||||
configure_table(devicetypes_table, request)
|
||||
devicetypes_table.configure(request)
|
||||
|
||||
return {
|
||||
'devicetypes_table': devicetypes_table,
|
||||
@ -1437,7 +1436,7 @@ class DeviceRoleView(generic.ObjectView):
|
||||
device_role=instance
|
||||
)
|
||||
devices_table = tables.DeviceTable(devices, exclude=('device_role',))
|
||||
configure_table(devices_table, request)
|
||||
devices_table.configure(request)
|
||||
|
||||
return {
|
||||
'devices_table': devices_table,
|
||||
@ -1501,7 +1500,7 @@ class PlatformView(generic.ObjectView):
|
||||
platform=instance
|
||||
)
|
||||
devices_table = tables.DeviceTable(devices, exclude=('platform',))
|
||||
configure_table(devices_table, request)
|
||||
devices_table.configure(request)
|
||||
|
||||
return {
|
||||
'devices_table': devices_table,
|
||||
|
@ -11,7 +11,6 @@ from rq import Worker
|
||||
from netbox.views import generic
|
||||
from utilities.forms import ConfirmationForm
|
||||
from utilities.htmx import is_htmx
|
||||
from netbox.tables import configure_table
|
||||
from utilities.utils import copy_safe_request, count_related, normalize_querydict, shallow_compare_dict
|
||||
from utilities.views import ContentTypePermissionRequiredMixin
|
||||
from . import filtersets, forms, tables
|
||||
@ -215,7 +214,7 @@ class TagView(generic.ObjectView):
|
||||
data=tagged_items,
|
||||
orderable=False
|
||||
)
|
||||
configure_table(taggeditem_table, request)
|
||||
taggeditem_table.configure(request)
|
||||
|
||||
object_types = [
|
||||
{
|
||||
@ -451,7 +450,7 @@ class ObjectChangeLogView(View):
|
||||
data=objectchanges,
|
||||
orderable=False
|
||||
)
|
||||
configure_table(objectchanges_table, request)
|
||||
objectchanges_table.configure(request)
|
||||
|
||||
# Default to using "<app>/<model>.html" as the template, if it exists. Otherwise,
|
||||
# fall back to using base.html.
|
||||
@ -571,7 +570,7 @@ class ObjectJournalView(View):
|
||||
assigned_object_id=obj.pk
|
||||
)
|
||||
journalentry_table = tables.ObjectJournalTable(journalentries)
|
||||
configure_table(journalentry_table, request)
|
||||
journalentry_table.configure(request)
|
||||
|
||||
if request.user.has_perm('extras.add_journalentry'):
|
||||
form = forms.JournalEntryForm(
|
||||
|
@ -8,7 +8,6 @@ from dcim.filtersets import InterfaceFilterSet
|
||||
from dcim.models import Interface, Site
|
||||
from dcim.tables import SiteTable
|
||||
from netbox.views import generic
|
||||
from netbox.tables import configure_table
|
||||
from utilities.utils import count_related
|
||||
from virtualization.filtersets import VMInterfaceFilterSet
|
||||
from virtualization.models import VMInterface
|
||||
@ -161,7 +160,7 @@ class RIRView(generic.ObjectView):
|
||||
rir=instance
|
||||
)
|
||||
aggregates_table = tables.AggregateTable(aggregates, exclude=('rir', 'utilization'))
|
||||
configure_table(aggregates_table, request)
|
||||
aggregates_table.configure(request)
|
||||
|
||||
return {
|
||||
'aggregates_table': aggregates_table,
|
||||
@ -219,7 +218,7 @@ class ASNView(generic.ObjectView):
|
||||
def get_extra_context(self, request, instance):
|
||||
sites = instance.sites.restrict(request.user, 'view')
|
||||
sites_table = SiteTable(sites)
|
||||
configure_table(sites_table, request)
|
||||
sites_table.configure(request)
|
||||
|
||||
return {
|
||||
'sites_table': sites_table,
|
||||
@ -357,7 +356,7 @@ class RoleView(generic.ObjectView):
|
||||
)
|
||||
|
||||
prefixes_table = tables.PrefixTable(prefixes, exclude=('role', 'utilization'))
|
||||
configure_table(prefixes_table, request)
|
||||
prefixes_table.configure(request)
|
||||
|
||||
return {
|
||||
'prefixes_table': prefixes_table,
|
||||
@ -662,7 +661,7 @@ class IPAddressView(generic.ObjectView):
|
||||
vrf=instance.vrf, address__net_contained_or_equal=str(instance.address)
|
||||
)
|
||||
related_ips_table = tables.IPAddressTable(related_ips, orderable=False)
|
||||
configure_table(related_ips_table, request)
|
||||
related_ips_table.configure(request)
|
||||
|
||||
return {
|
||||
'parent_prefixes_table': parent_prefixes_table,
|
||||
@ -798,7 +797,7 @@ class VLANGroupView(generic.ObjectView):
|
||||
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'):
|
||||
vlans_table.columns.show('pk')
|
||||
configure_table(vlans_table, request)
|
||||
vlans_table.configure(request)
|
||||
|
||||
# Compile permissions list for rendering the object table
|
||||
permissions = {
|
||||
|
@ -1,29 +1,2 @@
|
||||
from django_tables2 import RequestConfig
|
||||
|
||||
from utilities.paginator import EnhancedPaginator, get_paginate_count
|
||||
from .columns import *
|
||||
from .tables import *
|
||||
|
||||
|
||||
def configure_table(table, request):
|
||||
"""
|
||||
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 = {
|
||||
'paginator_class': EnhancedPaginator,
|
||||
'per_page': get_paginate_count(request)
|
||||
}
|
||||
RequestConfig(request, paginate).configure(table)
|
||||
|
@ -8,6 +8,7 @@ from django_tables2.data import TableQuerysetData
|
||||
|
||||
from extras.models import CustomField, CustomLink
|
||||
from netbox.tables import columns
|
||||
from utilities.paginator import EnhancedPaginator, get_paginate_count
|
||||
|
||||
__all__ = (
|
||||
'BaseTable',
|
||||
@ -166,3 +167,27 @@ class NetBoxTable(BaseTable):
|
||||
])
|
||||
|
||||
super().__init__(*args, extra_columns=extra_columns, **kwargs)
|
||||
|
||||
def configure(self, request):
|
||||
"""
|
||||
Configure the table for a specific request context. This performs pagination and records
|
||||
the user's preferred ordering logic.
|
||||
"""
|
||||
# Save ordering preference
|
||||
if request.user.is_authenticated:
|
||||
table_name = self.__class__.__name__
|
||||
if self.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(self.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).
|
||||
self.order_by = ordering
|
||||
|
||||
# Paginate the table results
|
||||
paginate = {
|
||||
'paginator_class': EnhancedPaginator,
|
||||
'per_page': get_paginate_count(request)
|
||||
}
|
||||
tables.RequestConfig(request, paginate).configure(self)
|
||||
|
@ -14,7 +14,6 @@ from django_tables2.export import TableExport
|
||||
|
||||
from extras.models import ExportTemplate
|
||||
from extras.signals import clear_webhooks
|
||||
from netbox.tables import configure_table
|
||||
from utilities.error_handlers import handle_protectederror
|
||||
from utilities.exceptions import PermissionsViolation
|
||||
from utilities.forms import (
|
||||
@ -169,7 +168,7 @@ class ObjectListView(BaseMultiObjectView):
|
||||
|
||||
# Render the objects table
|
||||
table = self.get_table(request, permissions)
|
||||
configure_table(table, request)
|
||||
table.configure(request)
|
||||
|
||||
# If this is an HTMX request, return only the rendered table HTML
|
||||
if is_htmx(request):
|
||||
|
@ -17,7 +17,6 @@ from utilities.exceptions import AbortTransaction, PermissionsViolation
|
||||
from utilities.forms import ConfirmationForm, ImportForm, restrict_form_fields
|
||||
from utilities.htmx import is_htmx
|
||||
from utilities.permissions import get_permission_for_model
|
||||
from netbox.tables import configure_table
|
||||
from utilities.utils import normalize_querydict, prepare_cloned_fields
|
||||
from utilities.views import GetReturnURLMixin
|
||||
from .base import BaseObjectView
|
||||
@ -124,7 +123,7 @@ class ObjectChildrenView(ObjectView):
|
||||
# Determine whether to display bulk action checkboxes
|
||||
if 'pk' in table.base_columns and (permissions['change'] or permissions['delete']):
|
||||
table.columns.show('pk')
|
||||
configure_table(table, request)
|
||||
table.configure(request)
|
||||
|
||||
# If this is an HTMX request, return only the rendered table HTML
|
||||
if is_htmx(request):
|
||||
|
@ -5,7 +5,6 @@ from circuits.models import Circuit
|
||||
from dcim.models import Cable, Device, Location, Rack, RackReservation, Site
|
||||
from ipam.models import Aggregate, IPAddress, Prefix, VLAN, VRF, ASN
|
||||
from netbox.views import generic
|
||||
from netbox.tables import configure_table
|
||||
from utilities.utils import count_related
|
||||
from virtualization.models import VirtualMachine, Cluster
|
||||
from . import filtersets, forms, tables
|
||||
@ -37,7 +36,7 @@ class TenantGroupView(generic.ObjectView):
|
||||
group=instance
|
||||
)
|
||||
tenants_table = tables.TenantTable(tenants, exclude=('group',))
|
||||
configure_table(tenants_table, request)
|
||||
tenants_table.configure(request)
|
||||
|
||||
return {
|
||||
'tenants_table': tenants_table,
|
||||
@ -186,7 +185,7 @@ class ContactGroupView(generic.ObjectView):
|
||||
group=instance
|
||||
)
|
||||
contacts_table = tables.ContactTable(contacts, exclude=('group',))
|
||||
configure_table(contacts_table, request)
|
||||
contacts_table.configure(request)
|
||||
|
||||
return {
|
||||
'child_groups_table': child_groups_table,
|
||||
@ -253,7 +252,7 @@ class ContactRoleView(generic.ObjectView):
|
||||
)
|
||||
contacts_table = tables.ContactAssignmentTable(contact_assignments)
|
||||
contacts_table.columns.hide('role')
|
||||
configure_table(contacts_table, request)
|
||||
contacts_table.configure(request)
|
||||
|
||||
return {
|
||||
'contacts_table': contacts_table,
|
||||
@ -310,7 +309,7 @@ class ContactView(generic.ObjectView):
|
||||
)
|
||||
assignments_table = tables.ContactAssignmentTable(contact_assignments)
|
||||
assignments_table.columns.hide('contact')
|
||||
configure_table(assignments_table, request)
|
||||
assignments_table.configure(request)
|
||||
|
||||
return {
|
||||
'assignments_table': assignments_table,
|
||||
|
@ -6,7 +6,6 @@ from django.urls import reverse
|
||||
from dcim.models import Site
|
||||
from dcim.tables import SiteTable
|
||||
from users.preferences import UserPreference
|
||||
from netbox.tables import configure_table
|
||||
from utilities.testing import TestCase
|
||||
|
||||
|
||||
@ -60,5 +59,5 @@ class UserPreferencesTest(TestCase):
|
||||
table = SiteTable(Site.objects.all())
|
||||
request = RequestFactory().get(url)
|
||||
request.user = self.user
|
||||
configure_table(table, request)
|
||||
table.configure(request)
|
||||
self.assertEqual(table.order_by, ('-status',))
|
||||
|
@ -11,7 +11,6 @@ from extras.views import ObjectConfigContextView
|
||||
from ipam.models import IPAddress, Service
|
||||
from ipam.tables import AssignedIPAddressesTable, InterfaceVLANTable
|
||||
from netbox.views import generic
|
||||
from netbox.tables import configure_table
|
||||
from utilities.utils import count_related
|
||||
from . import filtersets, forms, tables
|
||||
from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface
|
||||
@ -41,7 +40,7 @@ class ClusterTypeView(generic.ObjectView):
|
||||
vm_count=count_related(VirtualMachine, 'cluster')
|
||||
)
|
||||
clusters_table = tables.ClusterTable(clusters, exclude=('type',))
|
||||
configure_table(clusters_table, request)
|
||||
clusters_table.configure(request)
|
||||
|
||||
return {
|
||||
'clusters_table': clusters_table,
|
||||
@ -103,7 +102,7 @@ class ClusterGroupView(generic.ObjectView):
|
||||
vm_count=count_related(VirtualMachine, 'cluster')
|
||||
)
|
||||
clusters_table = tables.ClusterTable(clusters, exclude=('group',))
|
||||
configure_table(clusters_table, request)
|
||||
clusters_table.configure(request)
|
||||
|
||||
return {
|
||||
'clusters_table': clusters_table,
|
||||
|
@ -1,6 +1,5 @@
|
||||
from dcim.models import Interface
|
||||
from netbox.views import generic
|
||||
from netbox.tables import configure_table
|
||||
from utilities.utils import count_related
|
||||
from . import filtersets, forms, tables
|
||||
from .models import *
|
||||
@ -31,7 +30,7 @@ class WirelessLANGroupView(generic.ObjectView):
|
||||
group=instance
|
||||
)
|
||||
wirelesslans_table = tables.WirelessLANTable(wirelesslans, exclude=('group',))
|
||||
configure_table(wirelesslans_table, request)
|
||||
wirelesslans_table.configure(request)
|
||||
|
||||
return {
|
||||
'wirelesslans_table': wirelesslans_table,
|
||||
@ -99,7 +98,7 @@ class WirelessLANView(generic.ObjectView):
|
||||
wireless_lans=instance
|
||||
)
|
||||
interfaces_table = tables.WirelessLANInterfacesTable(attached_interfaces)
|
||||
configure_table(interfaces_table, request)
|
||||
interfaces_table.configure(request)
|
||||
|
||||
return {
|
||||
'interfaces_table': interfaces_table,
|
||||
|
Reference in New Issue
Block a user