mirror of
https://github.com/netbox-community/netbox.git
synced 2026-02-05 14:56:24 -06:00
* 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:
@@ -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')),
|
||||
)
|
||||
|
||||
@@ -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')),
|
||||
)
|
||||
|
||||
@@ -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'),
|
||||
|
||||
@@ -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'),
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -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'}}
|
||||
)
|
||||
|
||||
|
||||
@@ -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'),
|
||||
)
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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([
|
||||
|
||||
Reference in New Issue
Block a user