mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Introduced SearchTable for improved performance
This commit is contained in:
@ -1,7 +1,7 @@
|
|||||||
import django_tables2 as tables
|
import django_tables2 as tables
|
||||||
from django_tables2.utils import Accessor
|
from django_tables2.utils import Accessor
|
||||||
|
|
||||||
from utilities.tables import BaseTable, ToggleColumn
|
from utilities.tables import BaseTable, SearchTable, ToggleColumn
|
||||||
|
|
||||||
from .models import Circuit, CircuitType, Provider
|
from .models import Circuit, CircuitType, Provider
|
||||||
|
|
||||||
@ -19,9 +19,7 @@ CIRCUITTYPE_ACTIONS = """
|
|||||||
|
|
||||||
class ProviderTable(BaseTable):
|
class ProviderTable(BaseTable):
|
||||||
pk = ToggleColumn()
|
pk = ToggleColumn()
|
||||||
name = tables.LinkColumn('circuits:provider', args=[Accessor('slug')], verbose_name='Name')
|
name = tables.LinkColumn()
|
||||||
asn = tables.Column(verbose_name='ASN')
|
|
||||||
account = tables.Column(verbose_name='Account')
|
|
||||||
circuit_count = tables.Column(accessor=Accessor('count_circuits'), verbose_name='Circuits')
|
circuit_count = tables.Column(accessor=Accessor('count_circuits'), verbose_name='Circuits')
|
||||||
|
|
||||||
class Meta(BaseTable.Meta):
|
class Meta(BaseTable.Meta):
|
||||||
@ -29,17 +27,25 @@ class ProviderTable(BaseTable):
|
|||||||
fields = ('pk', 'name', 'asn', 'account', 'circuit_count')
|
fields = ('pk', 'name', 'asn', 'account', 'circuit_count')
|
||||||
|
|
||||||
|
|
||||||
|
class ProviderSearchTable(SearchTable):
|
||||||
|
name = tables.LinkColumn()
|
||||||
|
|
||||||
|
class Meta(SearchTable.Meta):
|
||||||
|
model = Provider
|
||||||
|
fields = ('name', 'asn', 'account')
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Circuit types
|
# Circuit types
|
||||||
#
|
#
|
||||||
|
|
||||||
class CircuitTypeTable(BaseTable):
|
class CircuitTypeTable(BaseTable):
|
||||||
pk = ToggleColumn()
|
pk = ToggleColumn()
|
||||||
name = tables.LinkColumn(verbose_name='Name')
|
name = tables.LinkColumn()
|
||||||
circuit_count = tables.Column(verbose_name='Circuits')
|
circuit_count = tables.Column(verbose_name='Circuits')
|
||||||
slug = tables.Column(verbose_name='Slug')
|
actions = tables.TemplateColumn(
|
||||||
actions = tables.TemplateColumn(template_code=CIRCUITTYPE_ACTIONS, attrs={'td': {'class': 'text-right'}},
|
template_code=CIRCUITTYPE_ACTIONS, attrs={'td': {'class': 'text-right'}}, verbose_name=''
|
||||||
verbose_name='')
|
)
|
||||||
|
|
||||||
class Meta(BaseTable.Meta):
|
class Meta(BaseTable.Meta):
|
||||||
model = CircuitType
|
model = CircuitType
|
||||||
@ -52,16 +58,28 @@ class CircuitTypeTable(BaseTable):
|
|||||||
|
|
||||||
class CircuitTable(BaseTable):
|
class CircuitTable(BaseTable):
|
||||||
pk = ToggleColumn()
|
pk = ToggleColumn()
|
||||||
cid = tables.LinkColumn('circuits:circuit', args=[Accessor('pk')], verbose_name='ID')
|
cid = tables.LinkColumn(verbose_name='ID')
|
||||||
type = tables.Column(verbose_name='Type')
|
provider = tables.LinkColumn('circuits:provider', args=[Accessor('provider.slug')])
|
||||||
provider = tables.LinkColumn('circuits:provider', args=[Accessor('provider.slug')], verbose_name='Provider')
|
tenant = tables.LinkColumn('tenancy:tenant', args=[Accessor('tenant.slug')])
|
||||||
tenant = tables.LinkColumn('tenancy:tenant', args=[Accessor('tenant.slug')], verbose_name='Tenant')
|
a_side = tables.LinkColumn(
|
||||||
a_side = tables.LinkColumn('dcim:site', accessor=Accessor('termination_a.site'), orderable=False,
|
'dcim:site', accessor=Accessor('termination_a.site'), orderable=False,
|
||||||
args=[Accessor('termination_a.site.slug')])
|
args=[Accessor('termination_a.site.slug')]
|
||||||
z_side = tables.LinkColumn('dcim:site', accessor=Accessor('termination_z.site'), orderable=False,
|
)
|
||||||
args=[Accessor('termination_z.site.slug')])
|
z_side = tables.LinkColumn(
|
||||||
description = tables.Column(verbose_name='Description')
|
'dcim:site', accessor=Accessor('termination_z.site'), orderable=False,
|
||||||
|
args=[Accessor('termination_z.site.slug')]
|
||||||
|
)
|
||||||
|
|
||||||
class Meta(BaseTable.Meta):
|
class Meta(BaseTable.Meta):
|
||||||
model = Circuit
|
model = Circuit
|
||||||
fields = ('pk', 'cid', 'type', 'provider', 'tenant', 'a_side', 'z_side', 'description')
|
fields = ('pk', 'cid', 'type', 'provider', 'tenant', 'a_side', 'z_side', 'description')
|
||||||
|
|
||||||
|
|
||||||
|
class CircuitSearchTable(SearchTable):
|
||||||
|
cid = tables.LinkColumn(verbose_name='ID')
|
||||||
|
provider = tables.LinkColumn('circuits:provider', args=[Accessor('provider.slug')])
|
||||||
|
tenant = tables.LinkColumn('tenancy:tenant', args=[Accessor('tenant.slug')])
|
||||||
|
|
||||||
|
class Meta(SearchTable.Meta):
|
||||||
|
model = Circuit
|
||||||
|
fields = ('cid', 'type', 'provider', 'tenant', 'description')
|
||||||
|
@ -8,9 +8,9 @@ from tenancy.models import Tenant
|
|||||||
from utilities.filters import NullableModelMultipleChoiceFilter, NumericInFilter
|
from utilities.filters import NullableModelMultipleChoiceFilter, NumericInFilter
|
||||||
from .models import (
|
from .models import (
|
||||||
ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay,
|
ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay,
|
||||||
DeviceBayTemplate, DeviceRole, DeviceType, IFACE_FF_LAG, Interface, InterfaceConnection, InterfaceTemplate,
|
DeviceBayTemplate, DeviceRole, DeviceType, IFACE_FF_LAG, Interface, InterfaceTemplate, Manufacturer, InventoryItem,
|
||||||
Manufacturer, InventoryItem, Platform, PowerOutlet, PowerOutletTemplate, PowerPort, PowerPortTemplate, Rack, RackGroup,
|
Platform, PowerOutlet, PowerOutletTemplate, PowerPort, PowerPortTemplate, Rack, RackGroup, RackReservation,
|
||||||
RackReservation, RackRole, Region, Site, VIRTUAL_IFACE_TYPES,
|
RackRole, Region, Site, VIRTUAL_IFACE_TYPES,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import django_tables2 as tables
|
import django_tables2 as tables
|
||||||
from django_tables2.utils import Accessor
|
from django_tables2.utils import Accessor
|
||||||
|
|
||||||
from utilities.tables import BaseTable, ToggleColumn
|
from utilities.tables import BaseTable, SearchTable, ToggleColumn
|
||||||
|
|
||||||
from .models import (
|
from .models import (
|
||||||
ConsolePort, ConsolePortTemplate, ConsoleServerPortTemplate, Device, DeviceBayTemplate, DeviceRole, DeviceType,
|
ConsolePort, ConsolePortTemplate, ConsoleServerPortTemplate, Device, DeviceBayTemplate, DeviceRole, DeviceType,
|
||||||
@ -136,11 +136,9 @@ class RegionTable(BaseTable):
|
|||||||
|
|
||||||
class SiteTable(BaseTable):
|
class SiteTable(BaseTable):
|
||||||
pk = ToggleColumn()
|
pk = ToggleColumn()
|
||||||
name = tables.LinkColumn('dcim:site', args=[Accessor('slug')], verbose_name='Name')
|
name = tables.LinkColumn()
|
||||||
facility = tables.Column(verbose_name='Facility')
|
region = tables.TemplateColumn(template_code=SITE_REGION_LINK)
|
||||||
region = tables.TemplateColumn(template_code=SITE_REGION_LINK, verbose_name='Region')
|
tenant = tables.LinkColumn('tenancy:tenant', args=[Accessor('tenant.slug')])
|
||||||
tenant = tables.LinkColumn('tenancy:tenant', args=[Accessor('tenant.slug')], verbose_name='Tenant')
|
|
||||||
asn = tables.Column(verbose_name='ASN')
|
|
||||||
rack_count = tables.Column(accessor=Accessor('count_racks'), orderable=False, verbose_name='Racks')
|
rack_count = tables.Column(accessor=Accessor('count_racks'), orderable=False, verbose_name='Racks')
|
||||||
device_count = tables.Column(accessor=Accessor('count_devices'), orderable=False, verbose_name='Devices')
|
device_count = tables.Column(accessor=Accessor('count_devices'), orderable=False, verbose_name='Devices')
|
||||||
prefix_count = tables.Column(accessor=Accessor('count_prefixes'), orderable=False, verbose_name='Prefixes')
|
prefix_count = tables.Column(accessor=Accessor('count_prefixes'), orderable=False, verbose_name='Prefixes')
|
||||||
@ -155,6 +153,16 @@ class SiteTable(BaseTable):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class SiteSearchTable(SearchTable):
|
||||||
|
name = tables.LinkColumn()
|
||||||
|
region = tables.TemplateColumn(template_code=SITE_REGION_LINK)
|
||||||
|
tenant = tables.LinkColumn('tenancy:tenant', args=[Accessor('tenant.slug')])
|
||||||
|
|
||||||
|
class Meta(SearchTable.Meta):
|
||||||
|
model = Site
|
||||||
|
fields = ('name', 'facility', 'region', 'tenant', 'asn')
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Rack groups
|
# Rack groups
|
||||||
#
|
#
|
||||||
@ -197,20 +205,33 @@ class RackRoleTable(BaseTable):
|
|||||||
|
|
||||||
class RackTable(BaseTable):
|
class RackTable(BaseTable):
|
||||||
pk = ToggleColumn()
|
pk = ToggleColumn()
|
||||||
name = tables.LinkColumn('dcim:rack', args=[Accessor('pk')], verbose_name='Name')
|
name = tables.LinkColumn()
|
||||||
site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')], verbose_name='Site')
|
site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')])
|
||||||
group = tables.Column(accessor=Accessor('group.name'), verbose_name='Group')
|
group = tables.Column(accessor=Accessor('group.name'), verbose_name='Group')
|
||||||
facility_id = tables.Column(verbose_name='Facility ID')
|
tenant = tables.LinkColumn('tenancy:tenant', args=[Accessor('tenant.slug')])
|
||||||
tenant = tables.LinkColumn('tenancy:tenant', args=[Accessor('tenant.slug')], verbose_name='Tenant')
|
role = tables.TemplateColumn(RACK_ROLE)
|
||||||
role = tables.TemplateColumn(RACK_ROLE, verbose_name='Role')
|
|
||||||
u_height = tables.TemplateColumn("{{ record.u_height }}U", verbose_name='Height')
|
u_height = tables.TemplateColumn("{{ record.u_height }}U", verbose_name='Height')
|
||||||
devices = tables.Column(accessor=Accessor('device_count'), verbose_name='Devices')
|
devices = tables.Column(accessor=Accessor('device_count'))
|
||||||
get_utilization = tables.TemplateColumn(UTILIZATION_GRAPH, orderable=False, verbose_name='Utilization')
|
get_utilization = tables.TemplateColumn(UTILIZATION_GRAPH, orderable=False, verbose_name='Utilization')
|
||||||
|
|
||||||
class Meta(BaseTable.Meta):
|
class Meta(BaseTable.Meta):
|
||||||
model = Rack
|
model = Rack
|
||||||
fields = ('pk', 'name', 'site', 'group', 'facility_id', 'tenant', 'role', 'u_height', 'devices',
|
fields = (
|
||||||
'get_utilization')
|
'pk', 'name', 'site', 'group', 'facility_id', 'tenant', 'role', 'u_height', 'devices', 'get_utilization'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class RackSearchTable(SearchTable):
|
||||||
|
name = tables.LinkColumn()
|
||||||
|
site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')])
|
||||||
|
group = tables.Column(accessor=Accessor('group.name'), verbose_name='Group')
|
||||||
|
tenant = tables.LinkColumn('tenancy:tenant', args=[Accessor('tenant.slug')])
|
||||||
|
role = tables.TemplateColumn(RACK_ROLE)
|
||||||
|
u_height = tables.TemplateColumn("{{ record.u_height }}U", verbose_name='Height')
|
||||||
|
|
||||||
|
class Meta(SearchTable.Meta):
|
||||||
|
model = Rack
|
||||||
|
fields = ('name', 'site', 'group', 'facility_id', 'tenant', 'role', 'u_height')
|
||||||
|
|
||||||
|
|
||||||
class RackImportTable(BaseTable):
|
class RackImportTable(BaseTable):
|
||||||
@ -249,9 +270,7 @@ class ManufacturerTable(BaseTable):
|
|||||||
|
|
||||||
class DeviceTypeTable(BaseTable):
|
class DeviceTypeTable(BaseTable):
|
||||||
pk = ToggleColumn()
|
pk = ToggleColumn()
|
||||||
manufacturer = tables.Column(verbose_name='Manufacturer')
|
|
||||||
model = tables.LinkColumn('dcim:devicetype', args=[Accessor('pk')], verbose_name='Device Type')
|
model = tables.LinkColumn('dcim:devicetype', args=[Accessor('pk')], verbose_name='Device Type')
|
||||||
part_number = tables.Column(verbose_name='Part Number')
|
|
||||||
is_full_depth = tables.BooleanColumn(verbose_name='Full Depth')
|
is_full_depth = tables.BooleanColumn(verbose_name='Full Depth')
|
||||||
is_console_server = tables.BooleanColumn(verbose_name='CS')
|
is_console_server = tables.BooleanColumn(verbose_name='CS')
|
||||||
is_pdu = tables.BooleanColumn(verbose_name='PDU')
|
is_pdu = tables.BooleanColumn(verbose_name='PDU')
|
||||||
@ -267,6 +286,22 @@ class DeviceTypeTable(BaseTable):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceTypeSearchTable(SearchTable):
|
||||||
|
model = tables.LinkColumn('dcim:devicetype', args=[Accessor('pk')], verbose_name='Device Type')
|
||||||
|
is_full_depth = tables.BooleanColumn(verbose_name='Full Depth')
|
||||||
|
is_console_server = tables.BooleanColumn(verbose_name='CS')
|
||||||
|
is_pdu = tables.BooleanColumn(verbose_name='PDU')
|
||||||
|
is_network_device = tables.BooleanColumn(verbose_name='Net')
|
||||||
|
subdevice_role = tables.TemplateColumn(SUBDEVICE_ROLE_TEMPLATE, verbose_name='Subdevice Role')
|
||||||
|
|
||||||
|
class Meta(SearchTable.Meta):
|
||||||
|
model = DeviceType
|
||||||
|
fields = (
|
||||||
|
'model', 'manufacturer', 'part_number', 'u_height', 'is_full_depth', 'is_console_server', 'is_pdu',
|
||||||
|
'is_network_device', 'subdevice_role',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Device type components
|
# Device type components
|
||||||
#
|
#
|
||||||
@ -373,22 +408,42 @@ class PlatformTable(BaseTable):
|
|||||||
|
|
||||||
class DeviceTable(BaseTable):
|
class DeviceTable(BaseTable):
|
||||||
pk = ToggleColumn()
|
pk = ToggleColumn()
|
||||||
|
name = tables.TemplateColumn(template_code=DEVICE_LINK)
|
||||||
status = tables.TemplateColumn(template_code=STATUS_ICON, verbose_name='')
|
status = tables.TemplateColumn(template_code=STATUS_ICON, verbose_name='')
|
||||||
name = tables.TemplateColumn(template_code=DEVICE_LINK, verbose_name='Name')
|
tenant = tables.LinkColumn('tenancy:tenant', args=[Accessor('tenant.slug')])
|
||||||
tenant = tables.LinkColumn('tenancy:tenant', args=[Accessor('tenant.slug')], verbose_name='Tenant')
|
site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')])
|
||||||
site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')], verbose_name='Site')
|
rack = tables.LinkColumn('dcim:rack', args=[Accessor('rack.pk')])
|
||||||
rack = tables.LinkColumn('dcim:rack', args=[Accessor('rack.pk')], verbose_name='Rack')
|
|
||||||
device_role = tables.TemplateColumn(DEVICE_ROLE, verbose_name='Role')
|
device_role = tables.TemplateColumn(DEVICE_ROLE, verbose_name='Role')
|
||||||
device_type = tables.LinkColumn('dcim:devicetype', args=[Accessor('device_type.pk')], verbose_name='Type',
|
device_type = tables.LinkColumn(
|
||||||
text=lambda record: record.device_type.full_name)
|
'dcim:devicetype', args=[Accessor('device_type.pk')], verbose_name='Type',
|
||||||
primary_ip = tables.TemplateColumn(orderable=False, verbose_name='IP Address',
|
text=lambda record: record.device_type.full_name
|
||||||
template_code=DEVICE_PRIMARY_IP)
|
)
|
||||||
|
primary_ip = tables.TemplateColumn(
|
||||||
|
orderable=False, verbose_name='IP Address', template_code=DEVICE_PRIMARY_IP
|
||||||
|
)
|
||||||
|
|
||||||
class Meta(BaseTable.Meta):
|
class Meta(BaseTable.Meta):
|
||||||
model = Device
|
model = Device
|
||||||
fields = ('pk', 'name', 'status', 'tenant', 'site', 'rack', 'device_role', 'device_type', 'primary_ip')
|
fields = ('pk', 'name', 'status', 'tenant', 'site', 'rack', 'device_role', 'device_type', 'primary_ip')
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceSearchTable(SearchTable):
|
||||||
|
name = tables.TemplateColumn(template_code=DEVICE_LINK)
|
||||||
|
status = tables.TemplateColumn(template_code=STATUS_ICON, verbose_name='')
|
||||||
|
tenant = tables.LinkColumn('tenancy:tenant', args=[Accessor('tenant.slug')])
|
||||||
|
site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')])
|
||||||
|
rack = tables.LinkColumn('dcim:rack', args=[Accessor('rack.pk')])
|
||||||
|
device_role = tables.TemplateColumn(DEVICE_ROLE, verbose_name='Role')
|
||||||
|
device_type = tables.LinkColumn(
|
||||||
|
'dcim:devicetype', args=[Accessor('device_type.pk')], verbose_name='Type',
|
||||||
|
text=lambda record: record.device_type.full_name
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta(SearchTable.Meta):
|
||||||
|
model = Device
|
||||||
|
fields = ('name', 'status', 'tenant', 'site', 'rack', 'device_role', 'device_type')
|
||||||
|
|
||||||
|
|
||||||
class DeviceImportTable(BaseTable):
|
class DeviceImportTable(BaseTable):
|
||||||
name = tables.TemplateColumn(template_code=DEVICE_LINK, verbose_name='Name')
|
name = tables.TemplateColumn(template_code=DEVICE_LINK, verbose_name='Name')
|
||||||
tenant = tables.LinkColumn('tenancy:tenant', args=[Accessor('tenant.slug')], verbose_name='Tenant')
|
tenant = tables.LinkColumn('tenancy:tenant', args=[Accessor('tenant.slug')], verbose_name='Tenant')
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import django_tables2 as tables
|
import django_tables2 as tables
|
||||||
from django_tables2.utils import Accessor
|
from django_tables2.utils import Accessor
|
||||||
|
|
||||||
from utilities.tables import BaseTable, ToggleColumn
|
from utilities.tables import BaseTable, SearchTable, ToggleColumn
|
||||||
|
|
||||||
from .models import Aggregate, IPAddress, Prefix, RIR, Role, VLAN, VLANGroup, VRF
|
from .models import Aggregate, IPAddress, Prefix, RIR, Role, VLAN, VLANGroup, VRF
|
||||||
|
|
||||||
@ -133,16 +133,25 @@ TENANT_LINK = """
|
|||||||
|
|
||||||
class VRFTable(BaseTable):
|
class VRFTable(BaseTable):
|
||||||
pk = ToggleColumn()
|
pk = ToggleColumn()
|
||||||
name = tables.LinkColumn('ipam:vrf', args=[Accessor('pk')], verbose_name='Name')
|
name = tables.LinkColumn()
|
||||||
rd = tables.Column(verbose_name='RD')
|
rd = tables.Column(verbose_name='RD')
|
||||||
tenant = tables.LinkColumn('tenancy:tenant', args=[Accessor('tenant.slug')], verbose_name='Tenant')
|
tenant = tables.LinkColumn('tenancy:tenant', args=[Accessor('tenant.slug')])
|
||||||
description = tables.Column(verbose_name='Description')
|
|
||||||
|
|
||||||
class Meta(BaseTable.Meta):
|
class Meta(BaseTable.Meta):
|
||||||
model = VRF
|
model = VRF
|
||||||
fields = ('pk', 'name', 'rd', 'tenant', 'description')
|
fields = ('pk', 'name', 'rd', 'tenant', 'description')
|
||||||
|
|
||||||
|
|
||||||
|
class VRFSearchTable(SearchTable):
|
||||||
|
name = tables.LinkColumn()
|
||||||
|
rd = tables.Column(verbose_name='RD')
|
||||||
|
tenant = tables.LinkColumn('tenancy:tenant', args=[Accessor('tenant.slug')])
|
||||||
|
|
||||||
|
class Meta(SearchTable.Meta):
|
||||||
|
model = VRF
|
||||||
|
fields = ('name', 'rd', 'tenant', 'description')
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# RIRs
|
# RIRs
|
||||||
#
|
#
|
||||||
@ -177,18 +186,25 @@ class RIRTable(BaseTable):
|
|||||||
|
|
||||||
class AggregateTable(BaseTable):
|
class AggregateTable(BaseTable):
|
||||||
pk = ToggleColumn()
|
pk = ToggleColumn()
|
||||||
prefix = tables.LinkColumn('ipam:aggregate', args=[Accessor('pk')], verbose_name='Aggregate')
|
prefix = tables.LinkColumn(verbose_name='Aggregate')
|
||||||
rir = tables.Column(verbose_name='RIR')
|
|
||||||
child_count = tables.Column(verbose_name='Prefixes')
|
child_count = tables.Column(verbose_name='Prefixes')
|
||||||
get_utilization = tables.TemplateColumn(UTILIZATION_GRAPH, orderable=False, verbose_name='Utilization')
|
get_utilization = tables.TemplateColumn(UTILIZATION_GRAPH, orderable=False, verbose_name='Utilization')
|
||||||
date_added = tables.DateColumn(format="Y-m-d", verbose_name='Added')
|
date_added = tables.DateColumn(format="Y-m-d", verbose_name='Added')
|
||||||
description = tables.Column(verbose_name='Description')
|
|
||||||
|
|
||||||
class Meta(BaseTable.Meta):
|
class Meta(BaseTable.Meta):
|
||||||
model = Aggregate
|
model = Aggregate
|
||||||
fields = ('pk', 'prefix', 'rir', 'child_count', 'get_utilization', 'date_added', 'description')
|
fields = ('pk', 'prefix', 'rir', 'child_count', 'get_utilization', 'date_added', 'description')
|
||||||
|
|
||||||
|
|
||||||
|
class AggregateSearchTable(SearchTable):
|
||||||
|
prefix = tables.LinkColumn(verbose_name='Aggregate')
|
||||||
|
date_added = tables.DateColumn(format="Y-m-d", verbose_name='Added')
|
||||||
|
|
||||||
|
class Meta(SearchTable.Meta):
|
||||||
|
model = Aggregate
|
||||||
|
fields = ('prefix', 'rir', 'date_added', 'description')
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Roles
|
# Roles
|
||||||
#
|
#
|
||||||
@ -212,14 +228,13 @@ class RoleTable(BaseTable):
|
|||||||
|
|
||||||
class PrefixTable(BaseTable):
|
class PrefixTable(BaseTable):
|
||||||
pk = ToggleColumn()
|
pk = ToggleColumn()
|
||||||
status = tables.TemplateColumn(STATUS_LABEL, verbose_name='Status')
|
prefix = tables.TemplateColumn(PREFIX_LINK, attrs={'th': {'style': 'padding-left: 17px'}})
|
||||||
prefix = tables.TemplateColumn(PREFIX_LINK, verbose_name='Prefix', attrs={'th': {'style': 'padding-left: 17px'}})
|
status = tables.TemplateColumn(STATUS_LABEL)
|
||||||
vrf = tables.TemplateColumn(VRF_LINK, verbose_name='VRF')
|
vrf = tables.TemplateColumn(VRF_LINK, verbose_name='VRF')
|
||||||
tenant = tables.TemplateColumn(TENANT_LINK, verbose_name='Tenant')
|
tenant = tables.TemplateColumn(TENANT_LINK)
|
||||||
site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')], verbose_name='Site')
|
site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')])
|
||||||
vlan = tables.LinkColumn('ipam:vlan', args=[Accessor('vlan.pk')], verbose_name='VLAN')
|
vlan = tables.LinkColumn('ipam:vlan', args=[Accessor('vlan.pk')], verbose_name='VLAN')
|
||||||
role = tables.TemplateColumn(PREFIX_ROLE_LINK, verbose_name='Role')
|
role = tables.TemplateColumn(PREFIX_ROLE_LINK)
|
||||||
description = tables.Column(verbose_name='Description')
|
|
||||||
|
|
||||||
class Meta(BaseTable.Meta):
|
class Meta(BaseTable.Meta):
|
||||||
model = Prefix
|
model = Prefix
|
||||||
@ -230,12 +245,11 @@ class PrefixTable(BaseTable):
|
|||||||
|
|
||||||
|
|
||||||
class PrefixBriefTable(BaseTable):
|
class PrefixBriefTable(BaseTable):
|
||||||
prefix = tables.TemplateColumn(PREFIX_LINK_BRIEF, verbose_name='Prefix')
|
prefix = tables.TemplateColumn(PREFIX_LINK_BRIEF)
|
||||||
vrf = tables.LinkColumn('ipam:vrf', args=[Accessor('vrf.pk')], default='Global', verbose_name='VRF')
|
vrf = tables.LinkColumn('ipam:vrf', args=[Accessor('vrf.pk')], default='Global')
|
||||||
site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')], verbose_name='Site')
|
site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')])
|
||||||
status = tables.TemplateColumn(STATUS_LABEL, verbose_name='Status')
|
status = tables.TemplateColumn(STATUS_LABEL)
|
||||||
vlan = tables.LinkColumn('ipam:vlan', args=[Accessor('vlan.pk')], verbose_name='VLAN')
|
vlan = tables.LinkColumn('ipam:vlan', args=[Accessor('vlan.pk')])
|
||||||
role = tables.Column(verbose_name='Role')
|
|
||||||
|
|
||||||
class Meta(BaseTable.Meta):
|
class Meta(BaseTable.Meta):
|
||||||
model = Prefix
|
model = Prefix
|
||||||
@ -243,6 +257,20 @@ class PrefixBriefTable(BaseTable):
|
|||||||
orderable = False
|
orderable = False
|
||||||
|
|
||||||
|
|
||||||
|
class PrefixSearchTable(SearchTable):
|
||||||
|
prefix = tables.TemplateColumn(PREFIX_LINK, attrs={'th': {'style': 'padding-left: 17px'}})
|
||||||
|
status = tables.TemplateColumn(STATUS_LABEL)
|
||||||
|
vrf = tables.TemplateColumn(VRF_LINK, verbose_name='VRF')
|
||||||
|
tenant = tables.TemplateColumn(TENANT_LINK)
|
||||||
|
site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')])
|
||||||
|
vlan = tables.LinkColumn('ipam:vlan', args=[Accessor('vlan.pk')], verbose_name='VLAN')
|
||||||
|
role = tables.TemplateColumn(PREFIX_ROLE_LINK)
|
||||||
|
|
||||||
|
class Meta(SearchTable.Meta):
|
||||||
|
model = Prefix
|
||||||
|
fields = ('prefix', 'status', 'vrf', 'tenant', 'site', 'vlan', 'role', 'description')
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# IPAddresses
|
# IPAddresses
|
||||||
#
|
#
|
||||||
@ -250,13 +278,11 @@ class PrefixBriefTable(BaseTable):
|
|||||||
class IPAddressTable(BaseTable):
|
class IPAddressTable(BaseTable):
|
||||||
pk = ToggleColumn()
|
pk = ToggleColumn()
|
||||||
address = tables.TemplateColumn(IPADDRESS_LINK, verbose_name='IP Address')
|
address = tables.TemplateColumn(IPADDRESS_LINK, verbose_name='IP Address')
|
||||||
status = tables.TemplateColumn(STATUS_LABEL, verbose_name='Status')
|
status = tables.TemplateColumn(STATUS_LABEL)
|
||||||
vrf = tables.TemplateColumn(VRF_LINK, verbose_name='VRF')
|
vrf = tables.TemplateColumn(VRF_LINK, verbose_name='VRF')
|
||||||
tenant = tables.TemplateColumn(TENANT_LINK, verbose_name='Tenant')
|
tenant = tables.TemplateColumn(TENANT_LINK)
|
||||||
device = tables.LinkColumn('dcim:device', args=[Accessor('interface.device.pk')], orderable=False,
|
device = tables.LinkColumn('dcim:device', args=[Accessor('interface.device.pk')], orderable=False)
|
||||||
verbose_name='Device')
|
interface = tables.Column(orderable=False)
|
||||||
interface = tables.Column(orderable=False, verbose_name='Interface')
|
|
||||||
description = tables.Column(verbose_name='Description')
|
|
||||||
|
|
||||||
class Meta(BaseTable.Meta):
|
class Meta(BaseTable.Meta):
|
||||||
model = IPAddress
|
model = IPAddress
|
||||||
@ -268,17 +294,30 @@ class IPAddressTable(BaseTable):
|
|||||||
|
|
||||||
class IPAddressBriefTable(BaseTable):
|
class IPAddressBriefTable(BaseTable):
|
||||||
address = tables.LinkColumn('ipam:ipaddress', args=[Accessor('pk')], verbose_name='IP Address')
|
address = tables.LinkColumn('ipam:ipaddress', args=[Accessor('pk')], verbose_name='IP Address')
|
||||||
device = tables.LinkColumn('dcim:device', args=[Accessor('interface.device.pk')], orderable=False,
|
device = tables.LinkColumn('dcim:device', args=[Accessor('interface.device.pk')], orderable=False)
|
||||||
verbose_name='Device')
|
interface = tables.Column(orderable=False)
|
||||||
interface = tables.Column(orderable=False, verbose_name='Interface')
|
nat_inside = tables.LinkColumn(
|
||||||
nat_inside = tables.LinkColumn('ipam:ipaddress', args=[Accessor('nat_inside.pk')], orderable=False,
|
'ipam:ipaddress', args=[Accessor('nat_inside.pk')], orderable=False, verbose_name='NAT (Inside)'
|
||||||
verbose_name='NAT (Inside)')
|
)
|
||||||
|
|
||||||
class Meta(BaseTable.Meta):
|
class Meta(BaseTable.Meta):
|
||||||
model = IPAddress
|
model = IPAddress
|
||||||
fields = ('address', 'device', 'interface', 'nat_inside')
|
fields = ('address', 'device', 'interface', 'nat_inside')
|
||||||
|
|
||||||
|
|
||||||
|
class IPAddressSearchTable(SearchTable):
|
||||||
|
address = tables.TemplateColumn(IPADDRESS_LINK, verbose_name='IP Address')
|
||||||
|
status = tables.TemplateColumn(STATUS_LABEL)
|
||||||
|
vrf = tables.TemplateColumn(VRF_LINK, verbose_name='VRF')
|
||||||
|
tenant = tables.TemplateColumn(TENANT_LINK)
|
||||||
|
device = tables.LinkColumn('dcim:device', args=[Accessor('interface.device.pk')], orderable=False)
|
||||||
|
interface = tables.Column(orderable=False)
|
||||||
|
|
||||||
|
class Meta(SearchTable.Meta):
|
||||||
|
model = IPAddress
|
||||||
|
fields = ('address', 'status', 'vrf', 'tenant', 'device', 'interface', 'description')
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# VLAN groups
|
# VLAN groups
|
||||||
#
|
#
|
||||||
@ -304,15 +343,26 @@ class VLANGroupTable(BaseTable):
|
|||||||
class VLANTable(BaseTable):
|
class VLANTable(BaseTable):
|
||||||
pk = ToggleColumn()
|
pk = ToggleColumn()
|
||||||
vid = tables.LinkColumn('ipam:vlan', args=[Accessor('pk')], verbose_name='ID')
|
vid = tables.LinkColumn('ipam:vlan', args=[Accessor('pk')], verbose_name='ID')
|
||||||
site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')], verbose_name='Site')
|
site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')])
|
||||||
group = tables.Column(accessor=Accessor('group.name'), verbose_name='Group')
|
group = tables.Column(accessor=Accessor('group.name'), verbose_name='Group')
|
||||||
name = tables.Column(verbose_name='Name')
|
|
||||||
prefixes = tables.TemplateColumn(VLAN_PREFIXES, orderable=False, verbose_name='Prefixes')
|
prefixes = tables.TemplateColumn(VLAN_PREFIXES, orderable=False, verbose_name='Prefixes')
|
||||||
tenant = tables.LinkColumn('tenancy:tenant', args=[Accessor('tenant.slug')], verbose_name='Tenant')
|
tenant = tables.LinkColumn('tenancy:tenant', args=[Accessor('tenant.slug')])
|
||||||
status = tables.TemplateColumn(STATUS_LABEL, verbose_name='Status')
|
status = tables.TemplateColumn(STATUS_LABEL)
|
||||||
role = tables.TemplateColumn(VLAN_ROLE_LINK, verbose_name='Role')
|
role = tables.TemplateColumn(VLAN_ROLE_LINK)
|
||||||
description = tables.Column(verbose_name='Description')
|
|
||||||
|
|
||||||
class Meta(BaseTable.Meta):
|
class Meta(BaseTable.Meta):
|
||||||
model = VLAN
|
model = VLAN
|
||||||
fields = ('pk', 'vid', 'site', 'group', 'name', 'prefixes', 'tenant', 'status', 'role', 'description')
|
fields = ('pk', 'vid', 'site', 'group', 'name', 'prefixes', 'tenant', 'status', 'role', 'description')
|
||||||
|
|
||||||
|
|
||||||
|
class VLANSearchTable(SearchTable):
|
||||||
|
vid = tables.LinkColumn('ipam:vlan', args=[Accessor('pk')], verbose_name='ID')
|
||||||
|
site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')])
|
||||||
|
group = tables.Column(accessor=Accessor('group.name'), verbose_name='Group')
|
||||||
|
tenant = tables.LinkColumn('tenancy:tenant', args=[Accessor('tenant.slug')])
|
||||||
|
status = tables.TemplateColumn(STATUS_LABEL)
|
||||||
|
role = tables.TemplateColumn(VLAN_ROLE_LINK)
|
||||||
|
|
||||||
|
class Meta(SearchTable.Meta):
|
||||||
|
model = VLAN
|
||||||
|
fields = ('vid', 'site', 'group', 'name', 'tenant', 'status', 'role', 'description')
|
||||||
|
@ -4,26 +4,25 @@ from rest_framework.views import APIView
|
|||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.reverse import reverse
|
from rest_framework.reverse import reverse
|
||||||
|
|
||||||
from django.db.models import Count
|
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.views.generic import View
|
from django.views.generic import View
|
||||||
|
|
||||||
from circuits.filters import CircuitFilter, ProviderFilter
|
from circuits.filters import CircuitFilter, ProviderFilter
|
||||||
from circuits.models import Circuit, Provider
|
from circuits.models import Circuit, Provider
|
||||||
from circuits.tables import CircuitTable, ProviderTable
|
from circuits.tables import CircuitSearchTable, ProviderSearchTable
|
||||||
from dcim.filters import DeviceFilter, DeviceTypeFilter, RackFilter, SiteFilter
|
from dcim.filters import DeviceFilter, DeviceTypeFilter, RackFilter, SiteFilter
|
||||||
from dcim.models import ConsolePort, Device, DeviceType, InterfaceConnection, PowerPort, Rack, Site
|
from dcim.models import ConsolePort, Device, DeviceType, InterfaceConnection, PowerPort, Rack, Site
|
||||||
from dcim.tables import DeviceTable, DeviceTypeTable, RackTable, SiteTable
|
from dcim.tables import DeviceSearchTable, DeviceTypeSearchTable, RackSearchTable, SiteSearchTable
|
||||||
from extras.models import UserAction
|
from extras.models import UserAction
|
||||||
from ipam.filters import AggregateFilter, IPAddressFilter, PrefixFilter, VLANFilter, VRFFilter
|
from ipam.filters import AggregateFilter, IPAddressFilter, PrefixFilter, VLANFilter, VRFFilter
|
||||||
from ipam.models import Aggregate, IPAddress, Prefix, VLAN, VRF
|
from ipam.models import Aggregate, IPAddress, Prefix, VLAN, VRF
|
||||||
from ipam.tables import AggregateTable, IPAddressTable, PrefixTable, VLANTable, VRFTable
|
from ipam.tables import AggregateSearchTable, IPAddressSearchTable, PrefixSearchTable, VLANSearchTable, VRFSearchTable
|
||||||
from secrets.filters import SecretFilter
|
from secrets.filters import SecretFilter
|
||||||
from secrets.models import Secret
|
from secrets.models import Secret
|
||||||
from secrets.tables import SecretTable
|
from secrets.tables import SecretSearchTable
|
||||||
from tenancy.filters import TenantFilter
|
from tenancy.filters import TenantFilter
|
||||||
from tenancy.models import Tenant
|
from tenancy.models import Tenant
|
||||||
from tenancy.tables import TenantTable
|
from tenancy.tables import TenantSearchTable
|
||||||
from .forms import SearchForm
|
from .forms import SearchForm
|
||||||
|
|
||||||
|
|
||||||
@ -31,89 +30,85 @@ SEARCH_MAX_RESULTS = 15
|
|||||||
SEARCH_TYPES = {
|
SEARCH_TYPES = {
|
||||||
# Circuits
|
# Circuits
|
||||||
'provider': {
|
'provider': {
|
||||||
'queryset': Provider.objects.annotate(count_circuits=Count('circuits')),
|
'queryset': Provider.objects.all(),
|
||||||
'filter': ProviderFilter,
|
'filter': ProviderFilter,
|
||||||
'table': ProviderTable,
|
'table': ProviderSearchTable,
|
||||||
'url': 'circuits:provider_list',
|
'url': 'circuits:provider_list',
|
||||||
},
|
},
|
||||||
'circuit': {
|
'circuit': {
|
||||||
'queryset': Circuit.objects.select_related('provider', 'type', 'tenant').prefetch_related(
|
'queryset': Circuit.objects.select_related('type', 'provider', 'tenant'),
|
||||||
'terminations__site'
|
|
||||||
),
|
|
||||||
'filter': CircuitFilter,
|
'filter': CircuitFilter,
|
||||||
'table': CircuitTable,
|
'table': CircuitSearchTable,
|
||||||
'url': 'circuits:circuit_list',
|
'url': 'circuits:circuit_list',
|
||||||
},
|
},
|
||||||
# DCIM
|
# DCIM
|
||||||
'site': {
|
'site': {
|
||||||
'queryset': Site.objects.select_related('region', 'tenant'),
|
'queryset': Site.objects.select_related('region', 'tenant'),
|
||||||
'filter': SiteFilter,
|
'filter': SiteFilter,
|
||||||
'table': SiteTable,
|
'table': SiteSearchTable,
|
||||||
'url': 'dcim:site_list',
|
'url': 'dcim:site_list',
|
||||||
},
|
},
|
||||||
'rack': {
|
'rack': {
|
||||||
'queryset': Rack.objects.select_related('site', 'group', 'tenant', 'role').prefetch_related('devices__device_type').annotate(device_count=Count('devices', distinct=True)),
|
'queryset': Rack.objects.select_related('site', 'group', 'tenant', 'role'),
|
||||||
'filter': RackFilter,
|
'filter': RackFilter,
|
||||||
'table': RackTable,
|
'table': RackSearchTable,
|
||||||
'url': 'dcim:rack_list',
|
'url': 'dcim:rack_list',
|
||||||
},
|
},
|
||||||
'devicetype': {
|
'devicetype': {
|
||||||
'queryset': DeviceType.objects.select_related('manufacturer').annotate(instance_count=Count('instances')),
|
'queryset': DeviceType.objects.select_related('manufacturer'),
|
||||||
'filter': DeviceTypeFilter,
|
'filter': DeviceTypeFilter,
|
||||||
'table': DeviceTypeTable,
|
'table': DeviceTypeSearchTable,
|
||||||
'url': 'dcim:devicetype_list',
|
'url': 'dcim:devicetype_list',
|
||||||
},
|
},
|
||||||
'device': {
|
'device': {
|
||||||
'queryset': Device.objects.select_related(
|
'queryset': Device.objects.select_related('device_type__manufacturer', 'device_role', 'tenant', 'site', 'rack'),
|
||||||
'device_type__manufacturer', 'device_role', 'tenant', 'site', 'rack', 'primary_ip4', 'primary_ip6'
|
|
||||||
),
|
|
||||||
'filter': DeviceFilter,
|
'filter': DeviceFilter,
|
||||||
'table': DeviceTable,
|
'table': DeviceSearchTable,
|
||||||
'url': 'dcim:device_list',
|
'url': 'dcim:device_list',
|
||||||
},
|
},
|
||||||
# IPAM
|
# IPAM
|
||||||
'vrf': {
|
'vrf': {
|
||||||
'queryset': VRF.objects.select_related('tenant'),
|
'queryset': VRF.objects.select_related('tenant'),
|
||||||
'filter': VRFFilter,
|
'filter': VRFFilter,
|
||||||
'table': VRFTable,
|
'table': VRFSearchTable,
|
||||||
'url': 'ipam:vrf_list',
|
'url': 'ipam:vrf_list',
|
||||||
},
|
},
|
||||||
'aggregate': {
|
'aggregate': {
|
||||||
'queryset': Aggregate.objects.select_related('rir'),
|
'queryset': Aggregate.objects.select_related('rir'),
|
||||||
'filter': AggregateFilter,
|
'filter': AggregateFilter,
|
||||||
'table': AggregateTable,
|
'table': AggregateSearchTable,
|
||||||
'url': 'ipam:aggregate_list',
|
'url': 'ipam:aggregate_list',
|
||||||
},
|
},
|
||||||
'prefix': {
|
'prefix': {
|
||||||
'queryset': Prefix.objects.select_related('site', 'vrf__tenant', 'tenant', 'vlan', 'role'),
|
'queryset': Prefix.objects.select_related('site', 'vrf__tenant', 'tenant', 'vlan', 'role'),
|
||||||
'filter': PrefixFilter,
|
'filter': PrefixFilter,
|
||||||
'table': PrefixTable,
|
'table': PrefixSearchTable,
|
||||||
'url': 'ipam:prefix_list',
|
'url': 'ipam:prefix_list',
|
||||||
},
|
},
|
||||||
'ipaddress': {
|
'ipaddress': {
|
||||||
'queryset': IPAddress.objects.select_related('vrf__tenant', 'tenant', 'interface__device'),
|
'queryset': IPAddress.objects.select_related('vrf__tenant', 'tenant', 'interface__device'),
|
||||||
'filter': IPAddressFilter,
|
'filter': IPAddressFilter,
|
||||||
'table': IPAddressTable,
|
'table': IPAddressSearchTable,
|
||||||
'url': 'ipam:ipaddress_list',
|
'url': 'ipam:ipaddress_list',
|
||||||
},
|
},
|
||||||
'vlan': {
|
'vlan': {
|
||||||
'queryset': VLAN.objects.select_related('site', 'group', 'tenant', 'role').prefetch_related('prefixes'),
|
'queryset': VLAN.objects.select_related('site', 'group', 'tenant', 'role'),
|
||||||
'filter': VLANFilter,
|
'filter': VLANFilter,
|
||||||
'table': VLANTable,
|
'table': VLANSearchTable,
|
||||||
'url': 'ipam:vlan_list',
|
'url': 'ipam:vlan_list',
|
||||||
},
|
},
|
||||||
# Secrets
|
# Secrets
|
||||||
'secret': {
|
'secret': {
|
||||||
'queryset': Secret.objects.select_related('role', 'device'),
|
'queryset': Secret.objects.select_related('role', 'device'),
|
||||||
'filter': SecretFilter,
|
'filter': SecretFilter,
|
||||||
'table': SecretTable,
|
'table': SecretSearchTable,
|
||||||
'url': 'secrets:secret_list',
|
'url': 'secrets:secret_list',
|
||||||
},
|
},
|
||||||
# Tenancy
|
# Tenancy
|
||||||
'tenant': {
|
'tenant': {
|
||||||
'queryset': Tenant.objects.select_related('group'),
|
'queryset': Tenant.objects.select_related('group'),
|
||||||
'filter': TenantFilter,
|
'filter': TenantFilter,
|
||||||
'table': TenantTable,
|
'table': TenantSearchTable,
|
||||||
'url': 'tenancy:tenant_list',
|
'url': 'tenancy:tenant_list',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -180,17 +175,21 @@ class SearchView(View):
|
|||||||
obj_types = SEARCH_TYPES.keys()
|
obj_types = SEARCH_TYPES.keys()
|
||||||
|
|
||||||
for obj_type in obj_types:
|
for obj_type in obj_types:
|
||||||
|
|
||||||
queryset = SEARCH_TYPES[obj_type]['queryset']
|
queryset = SEARCH_TYPES[obj_type]['queryset']
|
||||||
filter = SEARCH_TYPES[obj_type]['filter']
|
filter_cls = SEARCH_TYPES[obj_type]['filter']
|
||||||
table = SEARCH_TYPES[obj_type]['table']
|
table = SEARCH_TYPES[obj_type]['table']
|
||||||
url = SEARCH_TYPES[obj_type]['url']
|
url = SEARCH_TYPES[obj_type]['url']
|
||||||
filtered_queryset = filter({'q': form.cleaned_data['q']}, queryset=queryset).qs
|
|
||||||
total_count = filtered_queryset.count()
|
# Construct the results table for this object type
|
||||||
if total_count:
|
filtered_queryset = filter_cls({'q': form.cleaned_data['q']}, queryset=queryset).qs
|
||||||
|
table = table(filtered_queryset)
|
||||||
|
table.paginate(per_page=SEARCH_MAX_RESULTS)
|
||||||
|
|
||||||
|
if table.page:
|
||||||
results.append({
|
results.append({
|
||||||
'name': queryset.model._meta.verbose_name_plural,
|
'name': queryset.model._meta.verbose_name_plural,
|
||||||
'table': table(filtered_queryset[:SEARCH_MAX_RESULTS]),
|
'table': table,
|
||||||
'total': total_count,
|
|
||||||
'url': '{}?q={}'.format(reverse(url), form.cleaned_data['q'])
|
'url': '{}?q={}'.format(reverse(url), form.cleaned_data['q'])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import django_tables2 as tables
|
import django_tables2 as tables
|
||||||
from django_tables2.utils import Accessor
|
from django_tables2.utils import Accessor
|
||||||
|
|
||||||
from utilities.tables import BaseTable, ToggleColumn
|
from utilities.tables import BaseTable, SearchTable, ToggleColumn
|
||||||
|
|
||||||
from .models import SecretRole, Secret
|
from .models import SecretRole, Secret
|
||||||
|
|
||||||
@ -36,11 +36,15 @@ class SecretRoleTable(BaseTable):
|
|||||||
|
|
||||||
class SecretTable(BaseTable):
|
class SecretTable(BaseTable):
|
||||||
pk = ToggleColumn()
|
pk = ToggleColumn()
|
||||||
device = tables.LinkColumn('secrets:secret', args=[Accessor('pk')], verbose_name='Device')
|
device = tables.LinkColumn()
|
||||||
role = tables.Column(verbose_name='Role')
|
|
||||||
name = tables.Column(verbose_name='Name')
|
|
||||||
last_updated = tables.DateTimeColumn(verbose_name='Last updated')
|
|
||||||
|
|
||||||
class Meta(BaseTable.Meta):
|
class Meta(BaseTable.Meta):
|
||||||
model = Secret
|
model = Secret
|
||||||
fields = ('pk', 'device', 'role', 'name', 'last_updated')
|
fields = ('pk', 'device', 'role', 'name', 'last_updated')
|
||||||
|
|
||||||
|
|
||||||
|
class SecretSearchTable(SearchTable):
|
||||||
|
|
||||||
|
class Meta(SearchTable.Meta):
|
||||||
|
model = Secret
|
||||||
|
fields = ('device', 'role', 'name', 'last_updated')
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
{% extends '_base.html' %}
|
{% extends '_base.html' %}
|
||||||
{% load form_helpers %}
|
{% load form_helpers %}
|
||||||
|
|
||||||
|
{% block title %}Search{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% if request.GET.q %}
|
{% if request.GET.q %}
|
||||||
{% include 'search_form.html' with search_form=form %}
|
{% include 'search_form.html' with search_form=form %}
|
||||||
@ -8,33 +10,31 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-10">
|
<div class="col-md-10">
|
||||||
{% for obj_type in results %}
|
{% for obj_type in results %}
|
||||||
<h3 id="{{ obj_type.name }}">{{ obj_type.name|title }}</h3>
|
<h3 id="{{ obj_type.name }}">{{ obj_type.name }}</h3>
|
||||||
{% include 'table.html' with table=obj_type.table %}
|
{% include 'table.html' with table=obj_type.table hide_paginator=True %}
|
||||||
{% if obj_type.total > obj_type.table.rows|length %}
|
{% if obj_type.table.page.has_next %}
|
||||||
<a href="{{ obj_type.url }}" class="btn btn-primary pull-right">
|
<a href="{{ obj_type.url }}" class="btn btn-primary pull-right">
|
||||||
<span class="fa fa-search" aria-hidden="true"></span>
|
<span class="fa fa-search" aria-hidden="true"></span>
|
||||||
All {{ obj_type.total }} results
|
All {{ obj_type.table.page.paginator.count }} results
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-2" style="padding-top: 20px;">
|
<div class="col-md-2" style="padding-top: 20px;">
|
||||||
{% if results %}
|
<div class="panel panel-default">
|
||||||
<div class="panel panel-default">
|
<div class="panel-heading">
|
||||||
<div class="panel-heading">
|
<strong>Search Results</strong>
|
||||||
<strong>Search Results</strong>
|
|
||||||
</div>
|
|
||||||
<div class="list-group">
|
|
||||||
{% for obj_type in results %}
|
|
||||||
<a href="#{{ obj_type.name }}" class="list-group-item">
|
|
||||||
{{ obj_type.name|title }}
|
|
||||||
<span class="badge">{{ obj_type.total }}</span>
|
|
||||||
</a>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
<div class="list-group">
|
||||||
|
{% for obj_type in results %}
|
||||||
|
<a href="#{{ obj_type.name }}" class="list-group-item">
|
||||||
|
{{ obj_type.name }}
|
||||||
|
<span class="badge">{{ obj_type.table.page.paginator.count }}</span>
|
||||||
|
</a>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
@ -4,5 +4,7 @@
|
|||||||
{# Extends the stock django_tables2 template to provide custom formatting of the pagination controls #}
|
{# Extends the stock django_tables2 template to provide custom formatting of the pagination controls #}
|
||||||
|
|
||||||
{% block pagination %}
|
{% block pagination %}
|
||||||
{% include 'paginator.html' %}
|
{% if not hide_paginator %}
|
||||||
|
{% include 'paginator.html' %}
|
||||||
|
{% endif %}
|
||||||
{% endblock pagination %}
|
{% endblock pagination %}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import django_tables2 as tables
|
import django_tables2 as tables
|
||||||
from django_tables2.utils import Accessor
|
from django_tables2.utils import Accessor
|
||||||
|
|
||||||
from utilities.tables import BaseTable, ToggleColumn
|
from utilities.tables import BaseTable, SearchTable, ToggleColumn
|
||||||
|
|
||||||
from .models import Tenant, TenantGroup
|
from .models import Tenant, TenantGroup
|
||||||
|
|
||||||
@ -36,10 +36,15 @@ class TenantGroupTable(BaseTable):
|
|||||||
|
|
||||||
class TenantTable(BaseTable):
|
class TenantTable(BaseTable):
|
||||||
pk = ToggleColumn()
|
pk = ToggleColumn()
|
||||||
name = tables.LinkColumn('tenancy:tenant', args=[Accessor('slug')], verbose_name='Name')
|
name = tables.LinkColumn()
|
||||||
group = tables.Column(verbose_name='Group')
|
|
||||||
description = tables.Column(verbose_name='Description')
|
|
||||||
|
|
||||||
class Meta(BaseTable.Meta):
|
class Meta(BaseTable.Meta):
|
||||||
model = Tenant
|
model = Tenant
|
||||||
fields = ('pk', 'name', 'group', 'description')
|
fields = ('pk', 'name', 'group', 'description')
|
||||||
|
|
||||||
|
|
||||||
|
class TenantSearchTable(SearchTable):
|
||||||
|
|
||||||
|
class Meta(SearchTable.Meta):
|
||||||
|
model = Tenant
|
||||||
|
fields = ('name', 'group', 'description')
|
||||||
|
@ -4,7 +4,9 @@ from django.utils.safestring import mark_safe
|
|||||||
|
|
||||||
|
|
||||||
class BaseTable(tables.Table):
|
class BaseTable(tables.Table):
|
||||||
|
"""
|
||||||
|
Default table for object lists
|
||||||
|
"""
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(BaseTable, self).__init__(*args, **kwargs)
|
super(BaseTable, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
@ -18,6 +20,17 @@ class BaseTable(tables.Table):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class SearchTable(tables.Table):
|
||||||
|
"""
|
||||||
|
Default table for search results
|
||||||
|
"""
|
||||||
|
class Meta:
|
||||||
|
attrs = {
|
||||||
|
'class': 'table table-hover',
|
||||||
|
}
|
||||||
|
orderable = False
|
||||||
|
|
||||||
|
|
||||||
class ToggleColumn(tables.CheckBoxColumn):
|
class ToggleColumn(tables.CheckBoxColumn):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
Reference in New Issue
Block a user