Closes #11279: Replace _name natural key sorting with collation (#18009)

* 11279 add collation

* 11279 add collation

* 11279 add collation

* 11279 add collation

* 11279 fix tables /tests

* 11279 fix tests

* 11279 refactor VirtualDisk

* Clean up migrations

* Misc cleanup

* Correct errant file inclusion

---------

Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
This commit is contained in:
Arthur Hanson
2024-11-15 06:32:09 -08:00
committed by GitHub
parent 75aeaab8ee
commit 6ab0792f02
35 changed files with 622 additions and 150 deletions
+5 -15
View File
@@ -76,7 +76,6 @@ class ComponentType(
"""
Base type for device/VM components
"""
_name: str
device: Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')]
@@ -93,7 +92,6 @@ class ComponentTemplateType(
"""
Base type for device/VM components
"""
_name: str
device_type: Annotated["DeviceTypeType", strawberry.lazy('dcim.graphql.types')]
@@ -181,7 +179,7 @@ class ConsolePortType(ModularComponentType, CabledObjectMixin, PathEndpointMixin
filters=ConsolePortTemplateFilter
)
class ConsolePortTemplateType(ModularComponentTemplateType):
_name: str
pass
@strawberry_django.type(
@@ -199,7 +197,7 @@ class ConsoleServerPortType(ModularComponentType, CabledObjectMixin, PathEndpoin
filters=ConsoleServerPortTemplateFilter
)
class ConsoleServerPortTemplateType(ModularComponentTemplateType):
_name: str
pass
@strawberry_django.type(
@@ -208,7 +206,6 @@ class ConsoleServerPortTemplateType(ModularComponentTemplateType):
filters=DeviceFilter
)
class DeviceType(ConfigContextMixin, ImageAttachmentsMixin, ContactsMixin, NetBoxObjectType):
_name: str
console_port_count: BigInt
console_server_port_count: BigInt
power_port_count: BigInt
@@ -273,7 +270,7 @@ class DeviceBayType(ComponentType):
filters=DeviceBayTemplateFilter
)
class DeviceBayTemplateType(ComponentTemplateType):
_name: str
pass
@strawberry_django.type(
@@ -282,7 +279,6 @@ class DeviceBayTemplateType(ComponentTemplateType):
filters=InventoryItemTemplateFilter
)
class InventoryItemTemplateType(ComponentTemplateType):
_name: str
role: Annotated["InventoryItemRoleType", strawberry.lazy('dcim.graphql.types')] | None
manufacturer: Annotated["ManufacturerType", strawberry.lazy('dcim.graphql.types')]
@@ -366,7 +362,6 @@ class FrontPortType(ModularComponentType, CabledObjectMixin):
filters=FrontPortTemplateFilter
)
class FrontPortTemplateType(ModularComponentTemplateType):
_name: str
color: str
rear_port: Annotated["RearPortTemplateType", strawberry.lazy('dcim.graphql.types')]
@@ -377,6 +372,7 @@ class FrontPortTemplateType(ModularComponentTemplateType):
filters=InterfaceFilter
)
class InterfaceType(IPAddressesMixin, ModularComponentType, CabledObjectMixin, PathEndpointMixin):
_name: str
mac_address: str | None
wwn: str | None
parent: Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')] | None
@@ -527,7 +523,7 @@ class ModuleBayType(ModularComponentType):
filters=ModuleBayTemplateFilter
)
class ModuleBayTemplateType(ModularComponentTemplateType):
_name: str
pass
@strawberry_django.type(
@@ -588,7 +584,6 @@ class PowerOutletType(ModularComponentType, CabledObjectMixin, PathEndpointMixin
filters=PowerOutletTemplateFilter
)
class PowerOutletTemplateType(ModularComponentTemplateType):
_name: str
power_port: Annotated["PowerPortTemplateType", strawberry.lazy('dcim.graphql.types')] | None
@@ -620,8 +615,6 @@ class PowerPortType(ModularComponentType, CabledObjectMixin, PathEndpointMixin):
filters=PowerPortTemplateFilter
)
class PowerPortTemplateType(ModularComponentTemplateType):
_name: str
poweroutlet_templates: List[Annotated["PowerOutletTemplateType", strawberry.lazy('dcim.graphql.types')]]
@@ -640,7 +633,6 @@ class RackTypeType(NetBoxObjectType):
filters=RackFilter
)
class RackType(VLANGroupsMixin, ImageAttachmentsMixin, ContactsMixin, NetBoxObjectType):
_name: str
site: Annotated["SiteType", strawberry.lazy('dcim.graphql.types')]
location: Annotated["LocationType", strawberry.lazy('dcim.graphql.types')] | None
tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
@@ -693,7 +685,6 @@ class RearPortType(ModularComponentType, CabledObjectMixin):
filters=RearPortTemplateFilter
)
class RearPortTemplateType(ModularComponentTemplateType):
_name: str
color: str
frontport_templates: List[Annotated["FrontPortTemplateType", strawberry.lazy('dcim.graphql.types')]]
@@ -729,7 +720,6 @@ class RegionType(VLANGroupsMixin, ContactsMixin, OrganizationalObjectType):
filters=SiteFilter
)
class SiteType(VLANGroupsMixin, ImageAttachmentsMixin, ContactsMixin, NetBoxObjectType):
_name: str
time_zone: str | None
region: Annotated["RegionType", strawberry.lazy('dcim.graphql.types')] | None
group: Annotated["SiteGroupType", strawberry.lazy('dcim.graphql.types')] | None
@@ -0,0 +1,17 @@
from django.contrib.postgres.operations import CreateCollation
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('dcim', '0196_qinq_svlan'),
]
operations = [
CreateCollation(
"natural_sort",
provider="icu",
locale="und-u-kn-true",
),
]
@@ -0,0 +1,318 @@
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dcim', '0197_natural_sort_collation'),
]
operations = [
migrations.AlterModelOptions(
name='site',
options={'ordering': ('name',)},
),
migrations.AlterField(
model_name='site',
name='name',
field=models.CharField(db_collation='natural_sort', max_length=100, unique=True),
),
migrations.AlterModelOptions(
name='consoleport',
options={'ordering': ('device', 'name')},
),
migrations.AlterModelOptions(
name='consoleporttemplate',
options={'ordering': ('device_type', 'module_type', 'name')},
),
migrations.AlterModelOptions(
name='consoleserverport',
options={'ordering': ('device', 'name')},
),
migrations.AlterModelOptions(
name='consoleserverporttemplate',
options={'ordering': ('device_type', 'module_type', 'name')},
),
migrations.AlterModelOptions(
name='device',
options={'ordering': ('name', 'pk')},
),
migrations.AlterModelOptions(
name='devicebay',
options={'ordering': ('device', 'name')},
),
migrations.AlterModelOptions(
name='devicebaytemplate',
options={'ordering': ('device_type', 'name')},
),
migrations.AlterModelOptions(
name='frontport',
options={'ordering': ('device', 'name')},
),
migrations.AlterModelOptions(
name='frontporttemplate',
options={'ordering': ('device_type', 'module_type', 'name')},
),
migrations.AlterModelOptions(
name='interfacetemplate',
options={'ordering': ('device_type', 'module_type', 'name')},
),
migrations.AlterModelOptions(
name='inventoryitem',
options={'ordering': ('device__id', 'parent__id', 'name')},
),
migrations.AlterModelOptions(
name='inventoryitemtemplate',
options={'ordering': ('device_type__id', 'parent__id', 'name')},
),
migrations.AlterModelOptions(
name='modulebay',
options={'ordering': ('device', 'name')},
),
migrations.AlterModelOptions(
name='modulebaytemplate',
options={'ordering': ('device_type', 'module_type', 'name')},
),
migrations.AlterModelOptions(
name='poweroutlet',
options={'ordering': ('device', 'name')},
),
migrations.AlterModelOptions(
name='poweroutlettemplate',
options={'ordering': ('device_type', 'module_type', 'name')},
),
migrations.AlterModelOptions(
name='powerport',
options={'ordering': ('device', 'name')},
),
migrations.AlterModelOptions(
name='powerporttemplate',
options={'ordering': ('device_type', 'module_type', 'name')},
),
migrations.AlterModelOptions(
name='rack',
options={'ordering': ('site', 'location', 'name', 'pk')},
),
migrations.AlterModelOptions(
name='rearport',
options={'ordering': ('device', 'name')},
),
migrations.AlterModelOptions(
name='rearporttemplate',
options={'ordering': ('device_type', 'module_type', 'name')},
),
migrations.RemoveField(
model_name='consoleport',
name='_name',
),
migrations.RemoveField(
model_name='consoleporttemplate',
name='_name',
),
migrations.RemoveField(
model_name='consoleserverport',
name='_name',
),
migrations.RemoveField(
model_name='consoleserverporttemplate',
name='_name',
),
migrations.RemoveField(
model_name='device',
name='_name',
),
migrations.RemoveField(
model_name='devicebay',
name='_name',
),
migrations.RemoveField(
model_name='devicebaytemplate',
name='_name',
),
migrations.RemoveField(
model_name='frontport',
name='_name',
),
migrations.RemoveField(
model_name='frontporttemplate',
name='_name',
),
migrations.RemoveField(
model_name='inventoryitem',
name='_name',
),
migrations.RemoveField(
model_name='inventoryitemtemplate',
name='_name',
),
migrations.RemoveField(
model_name='modulebay',
name='_name',
),
migrations.RemoveField(
model_name='modulebaytemplate',
name='_name',
),
migrations.RemoveField(
model_name='poweroutlet',
name='_name',
),
migrations.RemoveField(
model_name='poweroutlettemplate',
name='_name',
),
migrations.RemoveField(
model_name='powerport',
name='_name',
),
migrations.RemoveField(
model_name='powerporttemplate',
name='_name',
),
migrations.RemoveField(
model_name='rack',
name='_name',
),
migrations.RemoveField(
model_name='rearport',
name='_name',
),
migrations.RemoveField(
model_name='rearporttemplate',
name='_name',
),
migrations.RemoveField(
model_name='site',
name='_name',
),
migrations.AlterField(
model_name='consoleport',
name='name',
field=models.CharField(db_collation='natural_sort', max_length=64),
),
migrations.AlterField(
model_name='consoleporttemplate',
name='name',
field=models.CharField(db_collation='natural_sort', max_length=64),
),
migrations.AlterField(
model_name='consoleserverport',
name='name',
field=models.CharField(db_collation='natural_sort', max_length=64),
),
migrations.AlterField(
model_name='consoleserverporttemplate',
name='name',
field=models.CharField(db_collation='natural_sort', max_length=64),
),
migrations.AlterField(
model_name='device',
name='name',
field=models.CharField(blank=True, db_collation='natural_sort', max_length=64, null=True),
),
migrations.AlterField(
model_name='devicebay',
name='name',
field=models.CharField(db_collation='natural_sort', max_length=64),
),
migrations.AlterField(
model_name='devicebaytemplate',
name='name',
field=models.CharField(db_collation='natural_sort', max_length=64),
),
migrations.AlterField(
model_name='frontport',
name='name',
field=models.CharField(db_collation='natural_sort', max_length=64),
),
migrations.AlterField(
model_name='frontporttemplate',
name='name',
field=models.CharField(db_collation='natural_sort', max_length=64),
),
migrations.AlterField(
model_name='interface',
name='name',
field=models.CharField(db_collation='natural_sort', max_length=64),
),
migrations.AlterField(
model_name='interfacetemplate',
name='name',
field=models.CharField(db_collation='natural_sort', max_length=64),
),
migrations.AlterField(
model_name='inventoryitem',
name='name',
field=models.CharField(db_collation='natural_sort', max_length=64),
),
migrations.AlterField(
model_name='inventoryitemtemplate',
name='name',
field=models.CharField(db_collation='natural_sort', max_length=64),
),
migrations.AlterField(
model_name='modulebay',
name='name',
field=models.CharField(db_collation='natural_sort', max_length=64),
),
migrations.AlterField(
model_name='modulebaytemplate',
name='name',
field=models.CharField(db_collation='natural_sort', max_length=64),
),
migrations.AlterField(
model_name='poweroutlet',
name='name',
field=models.CharField(db_collation='natural_sort', max_length=64),
),
migrations.AlterField(
model_name='poweroutlettemplate',
name='name',
field=models.CharField(db_collation='natural_sort', max_length=64),
),
migrations.AlterField(
model_name='powerport',
name='name',
field=models.CharField(db_collation='natural_sort', max_length=64),
),
migrations.AlterField(
model_name='powerporttemplate',
name='name',
field=models.CharField(db_collation='natural_sort', max_length=64),
),
migrations.AlterField(
model_name='rack',
name='name',
field=models.CharField(db_collation='natural_sort', max_length=100),
),
migrations.AlterField(
model_name='rearport',
name='name',
field=models.CharField(db_collation='natural_sort', max_length=64),
),
migrations.AlterField(
model_name='rearporttemplate',
name='name',
field=models.CharField(db_collation='natural_sort', max_length=64),
),
migrations.AlterField(
model_name='powerfeed',
name='name',
field=models.CharField(db_collation='natural_sort', max_length=100),
),
migrations.AlterField(
model_name='powerpanel',
name='name',
field=models.CharField(db_collation='natural_sort', max_length=100),
),
migrations.AlterField(
model_name='virtualchassis',
name='name',
field=models.CharField(db_collation='natural_sort', max_length=64),
),
migrations.AlterField(
model_name='virtualdevicecontext',
name='name',
field=models.CharField(db_collation='natural_sort', max_length=64),
),
]
@@ -44,12 +44,8 @@ class ComponentTemplateModel(ChangeLoggedModel, TrackingModelMixin):
max_length=64,
help_text=_(
"{module} is accepted as a substitution for the module bay position when attached to a module type."
)
)
_name = NaturalOrderingField(
target_field='name',
max_length=100,
blank=True
),
db_collation="natural_sort"
)
label = models.CharField(
verbose_name=_('label'),
@@ -65,7 +61,7 @@ class ComponentTemplateModel(ChangeLoggedModel, TrackingModelMixin):
class Meta:
abstract = True
ordering = ('device_type', '_name')
ordering = ('device_type', 'name')
constraints = (
models.UniqueConstraint(
fields=('device_type', 'name'),
@@ -125,7 +121,7 @@ class ModularComponentTemplateModel(ComponentTemplateModel):
class Meta:
abstract = True
ordering = ('device_type', 'module_type', '_name')
ordering = ('device_type', 'module_type', 'name')
constraints = (
models.UniqueConstraint(
fields=('device_type', 'name'),
@@ -782,7 +778,7 @@ class InventoryItemTemplate(MPTTModel, ComponentTemplateModel):
component_model = InventoryItem
class Meta:
ordering = ('device_type__id', 'parent__id', '_name')
ordering = ('device_type__id', 'parent__id', 'name')
indexes = (
models.Index(fields=('component_type', 'component_id')),
)
+4 -8
View File
@@ -50,12 +50,8 @@ class ComponentModel(NetBoxModel):
)
name = models.CharField(
verbose_name=_('name'),
max_length=64
)
_name = NaturalOrderingField(
target_field='name',
max_length=100,
blank=True
max_length=64,
db_collation="natural_sort"
)
label = models.CharField(
verbose_name=_('label'),
@@ -71,7 +67,7 @@ class ComponentModel(NetBoxModel):
class Meta:
abstract = True
ordering = ('device', '_name')
ordering = ('device', 'name')
constraints = (
models.UniqueConstraint(
fields=('device', 'name'),
@@ -1301,7 +1297,7 @@ class InventoryItem(MPTTModel, ComponentModel, TrackingModelMixin):
clone_fields = ('device', 'parent', 'role', 'manufacturer', 'status', 'part_id')
class Meta:
ordering = ('device__id', 'parent__id', '_name')
ordering = ('device__id', 'parent__id', 'name')
indexes = (
models.Index(fields=('component_type', 'component_id')),
)
+8 -11
View File
@@ -23,7 +23,7 @@ from netbox.config import ConfigItem
from netbox.models import OrganizationalModel, PrimaryModel
from netbox.models.mixins import WeightMixin
from netbox.models.features import ContactsMixin, ImageAttachmentsMixin
from utilities.fields import ColorField, CounterCacheField, NaturalOrderingField
from utilities.fields import ColorField, CounterCacheField
from utilities.tracking import TrackingModelMixin
from .device_components import *
from .mixins import RenderConfigMixin
@@ -582,13 +582,8 @@ class Device(
verbose_name=_('name'),
max_length=64,
blank=True,
null=True
)
_name = NaturalOrderingField(
target_field='name',
max_length=100,
blank=True,
null=True
null=True,
db_collation="natural_sort"
)
serial = models.CharField(
max_length=50,
@@ -775,7 +770,7 @@ class Device(
)
class Meta:
ordering = ('_name', 'pk') # Name may be null
ordering = ('name', 'pk') # Name may be null
constraints = (
models.UniqueConstraint(
Lower('name'), 'site', 'tenant',
@@ -1320,7 +1315,8 @@ class VirtualChassis(PrimaryModel):
)
name = models.CharField(
verbose_name=_('name'),
max_length=64
max_length=64,
db_collation="natural_sort"
)
domain = models.CharField(
verbose_name=_('domain'),
@@ -1382,7 +1378,8 @@ class VirtualDeviceContext(PrimaryModel):
)
name = models.CharField(
verbose_name=_('name'),
max_length=64
max_length=64,
db_collation="natural_sort"
)
status = models.CharField(
verbose_name=_('status'),
+4 -2
View File
@@ -36,7 +36,8 @@ class PowerPanel(ContactsMixin, ImageAttachmentsMixin, PrimaryModel):
)
name = models.CharField(
verbose_name=_('name'),
max_length=100
max_length=100,
db_collation="natural_sort"
)
prerequisite_models = (
@@ -86,7 +87,8 @@ class PowerFeed(PrimaryModel, PathEndpoint, CabledObjectModel):
)
name = models.CharField(
verbose_name=_('name'),
max_length=100
max_length=100,
db_collation="natural_sort"
)
status = models.CharField(
verbose_name=_('status'),
+3 -7
View File
@@ -19,7 +19,7 @@ from netbox.models.mixins import WeightMixin
from netbox.models.features import ContactsMixin, ImageAttachmentsMixin
from utilities.conversion import to_grams
from utilities.data import array_to_string, drange
from utilities.fields import ColorField, NaturalOrderingField
from utilities.fields import ColorField
from .device_components import PowerPort
from .devices import Device, Module
from .power import PowerFeed
@@ -255,12 +255,8 @@ class Rack(ContactsMixin, ImageAttachmentsMixin, RackBase):
)
name = models.CharField(
verbose_name=_('name'),
max_length=100
)
_name = NaturalOrderingField(
target_field='name',
max_length=100,
blank=True
db_collation="natural_sort"
)
facility_id = models.CharField(
max_length=50,
@@ -340,7 +336,7 @@ class Rack(ContactsMixin, ImageAttachmentsMixin, RackBase):
)
class Meta:
ordering = ('site', 'location', '_name', 'pk') # (site, location, name) may be non-unique
ordering = ('site', 'location', 'name', 'pk') # (site, location, name) may be non-unique
constraints = (
# Name and facility_id must be unique *only* within a Location
models.UniqueConstraint(
+3 -8
View File
@@ -8,7 +8,6 @@ from dcim.choices import *
from dcim.constants import *
from netbox.models import NestedGroupModel, PrimaryModel
from netbox.models.features import ContactsMixin, ImageAttachmentsMixin
from utilities.fields import NaturalOrderingField
__all__ = (
'Location',
@@ -143,12 +142,8 @@ class Site(ContactsMixin, ImageAttachmentsMixin, PrimaryModel):
verbose_name=_('name'),
max_length=100,
unique=True,
help_text=_("Full name of the site")
)
_name = NaturalOrderingField(
target_field='name',
max_length=100,
blank=True
help_text=_("Full name of the site"),
db_collation="natural_sort"
)
slug = models.SlugField(
verbose_name=_('slug'),
@@ -245,7 +240,7 @@ class Site(ContactsMixin, ImageAttachmentsMixin, PrimaryModel):
)
class Meta:
ordering = ('_name',)
ordering = ('name',)
verbose_name = _('site')
verbose_name_plural = _('sites')
+6 -12
View File
@@ -132,7 +132,6 @@ class PlatformTable(NetBoxTable):
class DeviceTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable):
name = tables.TemplateColumn(
verbose_name=_('Name'),
order_by=('_name',),
template_code=DEVICE_LINK,
linkify=True
)
@@ -288,7 +287,6 @@ class DeviceComponentTable(NetBoxTable):
name = tables.Column(
verbose_name=_('Name'),
linkify=True,
order_by=('_name',)
)
device_status = columns.ChoiceFieldColumn(
accessor=tables.A('device__status'),
@@ -391,7 +389,6 @@ class DeviceConsolePortTable(ConsolePortTable):
name = tables.TemplateColumn(
verbose_name=_('Name'),
template_code='<i class="mdi mdi-console"></i> <a href="{{ record.get_absolute_url }}">{{ value }}</a>',
order_by=Accessor('_name'),
attrs={'td': {'class': 'text-nowrap'}}
)
actions = columns.ActionsColumn(
@@ -433,7 +430,6 @@ class DeviceConsoleServerPortTable(ConsoleServerPortTable):
verbose_name=_('Name'),
template_code='<i class="mdi mdi-console-network-outline"></i> '
'<a href="{{ record.get_absolute_url }}">{{ value }}</a>',
order_by=Accessor('_name'),
attrs={'td': {'class': 'text-nowrap'}}
)
actions = columns.ActionsColumn(
@@ -482,7 +478,6 @@ class DevicePowerPortTable(PowerPortTable):
verbose_name=_('Name'),
template_code='<i class="mdi mdi-power-plug-outline"></i> <a href="{{ record.get_absolute_url }}">'
'{{ value }}</a>',
order_by=Accessor('_name'),
attrs={'td': {'class': 'text-nowrap'}}
)
actions = columns.ActionsColumn(
@@ -531,7 +526,6 @@ class DevicePowerOutletTable(PowerOutletTable):
name = tables.TemplateColumn(
verbose_name=_('Name'),
template_code='<i class="mdi mdi-power-socket"></i> <a href="{{ record.get_absolute_url }}">{{ value }}</a>',
order_by=Accessor('_name'),
attrs={'td': {'class': 'text-nowrap'}}
)
actions = columns.ActionsColumn(
@@ -550,6 +544,11 @@ class DevicePowerOutletTable(PowerOutletTable):
class BaseInterfaceTable(NetBoxTable):
name = tables.Column(
verbose_name=_('Name'),
linkify=True,
order_by=('_name',)
)
enabled = columns.BooleanColumn(
verbose_name=_('Enabled'),
)
@@ -597,7 +596,7 @@ class BaseInterfaceTable(NetBoxTable):
return ",".join([str(obj) for obj in value.all()])
class InterfaceTable(ModularDeviceComponentTable, BaseInterfaceTable, PathEndpointTable):
class InterfaceTable(BaseInterfaceTable, ModularDeviceComponentTable, PathEndpointTable):
device = tables.Column(
verbose_name=_('Device'),
linkify={
@@ -736,7 +735,6 @@ class DeviceFrontPortTable(FrontPortTable):
verbose_name=_('Name'),
template_code='<i class="mdi mdi-square-rounded{% if not record.cable %}-outline{% endif %}"></i> '
'<a href="{{ record.get_absolute_url }}">{{ value }}</a>',
order_by=Accessor('_name'),
attrs={'td': {'class': 'text-nowrap'}}
)
actions = columns.ActionsColumn(
@@ -783,7 +781,6 @@ class DeviceRearPortTable(RearPortTable):
verbose_name=_('Name'),
template_code='<i class="mdi mdi-square-rounded{% if not record.cable %}-outline{% endif %}"></i> '
'<a href="{{ record.get_absolute_url }}">{{ value }}</a>',
order_by=Accessor('_name'),
attrs={'td': {'class': 'text-nowrap'}}
)
actions = columns.ActionsColumn(
@@ -846,7 +843,6 @@ class DeviceDeviceBayTable(DeviceBayTable):
verbose_name=_('Name'),
template_code='<i class="mdi mdi-circle{% if record.installed_device %}slice-8{% else %}outline{% endif %}'
'"></i> <a href="{{ record.get_absolute_url }}">{{ value }}</a>',
order_by=Accessor('_name'),
attrs={'td': {'class': 'text-nowrap'}}
)
actions = columns.ActionsColumn(
@@ -915,7 +911,6 @@ class DeviceModuleBayTable(ModuleBayTable):
name = columns.MPTTColumn(
verbose_name=_('Name'),
linkify=True,
order_by=Accessor('_name')
)
actions = columns.ActionsColumn(
extra_buttons=MODULEBAY_BUTTONS
@@ -982,7 +977,6 @@ class DeviceInventoryItemTable(InventoryItemTable):
verbose_name=_('Name'),
template_code='<a href="{{ record.get_absolute_url }}" style="padding-left: {{ record.level }}0px">'
'{{ value }}</a>',
order_by=Accessor('_name'),
attrs={'td': {'class': 'text-nowrap'}}
)
+5 -3
View File
@@ -163,9 +163,7 @@ class ComponentTemplateTable(NetBoxTable):
id = tables.Column(
verbose_name=_('ID')
)
name = tables.Column(
order_by=('_name',)
)
name = tables.Column()
class Meta(NetBoxTable.Meta):
exclude = ('id', )
@@ -220,6 +218,10 @@ class PowerOutletTemplateTable(ComponentTemplateTable):
class InterfaceTemplateTable(ComponentTemplateTable):
name = tables.Column(
verbose_name=_('Name'),
order_by=('_name',)
)
enabled = columns.BooleanColumn(
verbose_name=_('Enabled'),
)
-1
View File
@@ -111,7 +111,6 @@ class RackTypeTable(NetBoxTable):
class RackTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable):
name = tables.Column(
verbose_name=_('Name'),
order_by=('_name',),
linkify=True
)
location = tables.Column(
+3 -4
View File
@@ -688,8 +688,7 @@ class RackElevationListView(generic.ObjectListView):
sort = request.GET.get('sort', 'name')
if sort not in ORDERING_CHOICES:
sort = 'name'
sort_field = sort.replace("name", "_name") # Use natural ordering
racks = racks.order_by(sort_field)
racks = racks.order_by(sort)
# Pagination
per_page = get_paginate_count(request)
@@ -731,8 +730,8 @@ class RackView(GetRelatedModelsMixin, generic.ObjectView):
peer_racks = peer_racks.filter(location=instance.location)
else:
peer_racks = peer_racks.filter(location__isnull=True)
next_rack = peer_racks.filter(_name__gt=instance._name).first()
prev_rack = peer_racks.filter(_name__lt=instance._name).reverse().first()
next_rack = peer_racks.filter(name__gt=instance.name).first()
prev_rack = peer_racks.filter(name__lt=instance.name).reverse().first()
# Determine any additional parameters to pass when embedding the rack elevations
svg_extra = '&'.join([