From 4062986e069600b7d2176a6c93389a81d1c681f0 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Date: Tue, 12 Nov 2024 14:41:54 -0800 Subject: [PATCH 01/10] 11279 add collation --- .../migrations/0197_auto_20241112_2221.py | 19 ++++++++++++++++ ...0198_alter_site_options_alter_site_name.py | 22 +++++++++++++++++++ netbox/dcim/models/sites.py | 5 +++-- 3 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 netbox/dcim/migrations/0197_auto_20241112_2221.py create mode 100644 netbox/dcim/migrations/0198_alter_site_options_alter_site_name.py diff --git a/netbox/dcim/migrations/0197_auto_20241112_2221.py b/netbox/dcim/migrations/0197_auto_20241112_2221.py new file mode 100644 index 00000000000..584f955a0fa --- /dev/null +++ b/netbox/dcim/migrations/0197_auto_20241112_2221.py @@ -0,0 +1,19 @@ +# Generated by Django 5.0.9 on 2024-11-12 22:21 + +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", + ), + ] diff --git a/netbox/dcim/migrations/0198_alter_site_options_alter_site_name.py b/netbox/dcim/migrations/0198_alter_site_options_alter_site_name.py new file mode 100644 index 00000000000..1dbab9cf7b3 --- /dev/null +++ b/netbox/dcim/migrations/0198_alter_site_options_alter_site_name.py @@ -0,0 +1,22 @@ +# Generated by Django 5.0.9 on 2024-11-12 22:26 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('dcim', '0197_auto_20241112_2221'), + ] + + 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), + ), + ] diff --git a/netbox/dcim/models/sites.py b/netbox/dcim/models/sites.py index a290f4119fe..442bd8b271f 100644 --- a/netbox/dcim/models/sites.py +++ b/netbox/dcim/models/sites.py @@ -143,7 +143,8 @@ class Site(ContactsMixin, ImageAttachmentsMixin, PrimaryModel): verbose_name=_('name'), max_length=100, unique=True, - help_text=_("Full name of the site") + help_text=_("Full name of the site"), + db_collation="natural_sort" ) _name = NaturalOrderingField( target_field='name', @@ -245,7 +246,7 @@ class Site(ContactsMixin, ImageAttachmentsMixin, PrimaryModel): ) class Meta: - ordering = ('_name',) + ordering = ('name',) verbose_name = _('site') verbose_name_plural = _('sites') From 33099499d653bd1208908aeb65f49b3d996166f2 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Date: Tue, 12 Nov 2024 15:00:46 -0800 Subject: [PATCH 02/10] 11279 add collation --- netbox/dcim/migrations/0197_auto_20241112_2221.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/dcim/migrations/0197_auto_20241112_2221.py b/netbox/dcim/migrations/0197_auto_20241112_2221.py index 584f955a0fa..02a8e42441d 100644 --- a/netbox/dcim/migrations/0197_auto_20241112_2221.py +++ b/netbox/dcim/migrations/0197_auto_20241112_2221.py @@ -14,6 +14,6 @@ class Migration(migrations.Migration): CreateCollation( "natural_sort", provider="icu", - locale="und-u-kn-true", + locale="und-u-ks-level2-kn-true", ), ] From fb19be9cca3b00b5c030c2223119389de2c16534 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Date: Wed, 13 Nov 2024 09:01:47 -0800 Subject: [PATCH 03/10] 11279 add collation --- .../migrations/0197_auto_20241112_2221.py | 19 -- netbox/dcim/migrations/0197_natural_sort.py | 306 ++++++++++++++++++ ...0198_alter_site_options_alter_site_name.py | 22 -- .../dcim/models/device_component_templates.py | 14 +- netbox/dcim/models/device_components.py | 12 +- netbox/dcim/models/devices.py | 13 +- netbox/dcim/models/racks.py | 10 +- netbox/dcim/models/sites.py | 6 - netbox/utilities/fields.py | 4 +- ...6_alter_virtualmachine_options_and_more.py | 37 +++ .../virtualization/models/virtualmachines.py | 13 +- 11 files changed, 366 insertions(+), 90 deletions(-) delete mode 100644 netbox/dcim/migrations/0197_auto_20241112_2221.py create mode 100644 netbox/dcim/migrations/0197_natural_sort.py delete mode 100644 netbox/dcim/migrations/0198_alter_site_options_alter_site_name.py create mode 100644 netbox/virtualization/migrations/0046_alter_virtualmachine_options_and_more.py diff --git a/netbox/dcim/migrations/0197_auto_20241112_2221.py b/netbox/dcim/migrations/0197_auto_20241112_2221.py deleted file mode 100644 index 02a8e42441d..00000000000 --- a/netbox/dcim/migrations/0197_auto_20241112_2221.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 5.0.9 on 2024-11-12 22:21 - -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-ks-level2-kn-true", - ), - ] diff --git a/netbox/dcim/migrations/0197_natural_sort.py b/netbox/dcim/migrations/0197_natural_sort.py new file mode 100644 index 00000000000..03e81e733bf --- /dev/null +++ b/netbox/dcim/migrations/0197_natural_sort.py @@ -0,0 +1,306 @@ +# Generated by Django 5.0.9 on 2024-11-12 22:21 + +from django.contrib.postgres.operations import CreateCollation +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('dcim', '0196_qinq_svlan'), + ] + + operations = [ + CreateCollation( + "natural_sort", + provider="icu", + locale="und-u-kn-true", + ), + 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), + ), + ] diff --git a/netbox/dcim/migrations/0198_alter_site_options_alter_site_name.py b/netbox/dcim/migrations/0198_alter_site_options_alter_site_name.py deleted file mode 100644 index 1dbab9cf7b3..00000000000 --- a/netbox/dcim/migrations/0198_alter_site_options_alter_site_name.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 5.0.9 on 2024-11-12 22:26 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('dcim', '0197_auto_20241112_2221'), - ] - - 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), - ), - ] diff --git a/netbox/dcim/models/device_component_templates.py b/netbox/dcim/models/device_component_templates.py index 00555d49e1b..ddd4d242674 100644 --- a/netbox/dcim/models/device_component_templates.py +++ b/netbox/dcim/models/device_component_templates.py @@ -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')), ) diff --git a/netbox/dcim/models/device_components.py b/netbox/dcim/models/device_components.py index 36fd02add46..31278a13c7c 100644 --- a/netbox/dcim/models/device_components.py +++ b/netbox/dcim/models/device_components.py @@ -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')), ) diff --git a/netbox/dcim/models/devices.py b/netbox/dcim/models/devices.py index 47f4ee6c9e5..2cb5ef4f32e 100644 --- a/netbox/dcim/models/devices.py +++ b/netbox/dcim/models/devices.py @@ -23,7 +23,7 @@ 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', diff --git a/netbox/dcim/models/racks.py b/netbox/dcim/models/racks.py index 013dfb61948..08b7f5a35ad 100644 --- a/netbox/dcim/models/racks.py +++ b/netbox/dcim/models/racks.py @@ -19,7 +19,7 @@ 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( diff --git a/netbox/dcim/models/sites.py b/netbox/dcim/models/sites.py index 442bd8b271f..0985a8d7af6 100644 --- a/netbox/dcim/models/sites.py +++ b/netbox/dcim/models/sites.py @@ -8,7 +8,6 @@ from dcim.constants import * from netbox.models import NestedGroupModel, PrimaryModel from netbox.models.features import ContactsMixin, ImageAttachmentsMixin -from utilities.fields import NaturalOrderingField __all__ = ( 'Location', @@ -146,11 +145,6 @@ class Site(ContactsMixin, ImageAttachmentsMixin, PrimaryModel): help_text=_("Full name of the site"), db_collation="natural_sort" ) - _name = NaturalOrderingField( - target_field='name', - max_length=100, - blank=True - ) slug = models.SlugField( verbose_name=_('slug'), max_length=100, diff --git a/netbox/utilities/fields.py b/netbox/utilities/fields.py index ee71223cb1b..c4ea13bc9f5 100644 --- a/netbox/utilities/fields.py +++ b/netbox/utilities/fields.py @@ -5,7 +5,7 @@ from django.utils.safestring import mark_safe from django.utils.translation import gettext_lazy as _ -from utilities.ordering import naturalize +from utilities.ordering import naturalize_interface from .forms.widgets import ColorSelect from .validators import ColorValidator @@ -40,7 +40,7 @@ class NaturalOrderingField(models.CharField): """ description = "Stores a representation of its target field suitable for natural ordering" - def __init__(self, target_field, naturalize_function=naturalize, *args, **kwargs): + def __init__(self, target_field, naturalize_function=naturalize_interface, *args, **kwargs): self.target_field = target_field self.naturalize_function = naturalize_function super().__init__(*args, **kwargs) diff --git a/netbox/virtualization/migrations/0046_alter_virtualmachine_options_and_more.py b/netbox/virtualization/migrations/0046_alter_virtualmachine_options_and_more.py new file mode 100644 index 00000000000..8114f73156a --- /dev/null +++ b/netbox/virtualization/migrations/0046_alter_virtualmachine_options_and_more.py @@ -0,0 +1,37 @@ +# Generated by Django 5.0.9 on 2024-11-13 16:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('virtualization', '0045_clusters_cached_relations'), + ('dcim', '0197_natural_sort'), + ] + + operations = [ + migrations.AlterModelOptions( + name='virtualmachine', + options={'ordering': ('name', 'pk')}, + ), + migrations.RemoveField( + model_name='virtualmachine', + name='_name', + ), + migrations.AlterField( + model_name='virtualdisk', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=64), + ), + migrations.AlterField( + model_name='virtualmachine', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=64), + ), + migrations.AlterField( + model_name='vminterface', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=64), + ), + ] diff --git a/netbox/virtualization/models/virtualmachines.py b/netbox/virtualization/models/virtualmachines.py index 4ee41e403ec..c83d76f02b9 100644 --- a/netbox/virtualization/models/virtualmachines.py +++ b/netbox/virtualization/models/virtualmachines.py @@ -69,12 +69,8 @@ class VirtualMachine(ContactsMixin, ImageAttachmentsMixin, RenderConfigMixin, Co ) 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" ) status = models.CharField( max_length=50, @@ -152,7 +148,7 @@ class VirtualMachine(ContactsMixin, ImageAttachmentsMixin, RenderConfigMixin, Co ) class Meta: - ordering = ('_name', 'pk') # Name may be non-unique + ordering = ('name', 'pk') # Name may be non-unique constraints = ( models.UniqueConstraint( Lower('name'), 'cluster', 'tenant', @@ -273,7 +269,8 @@ class ComponentModel(NetBoxModel): ) name = models.CharField( verbose_name=_('name'), - max_length=64 + max_length=64, + db_collation="natural_sort" ) _name = NaturalOrderingField( target_field='name', From 5518286c792d09a5e21700c3e71aecc2117495b5 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Date: Wed, 13 Nov 2024 09:19:41 -0800 Subject: [PATCH 04/10] 11279 add collation --- ...rovider_name_alter_providernetwork_name.py | 24 +++++++++ netbox/circuits/models/providers.py | 6 ++- netbox/dcim/migrations/0197_natural_sort.py | 20 ++++++++ netbox/dcim/models/devices.py | 6 ++- netbox/dcim/models/power.py | 6 ++- ...ge_name_alter_routetarget_name_and_more.py | 34 +++++++++++++ netbox/ipam/models/asns.py | 3 +- netbox/ipam/models/vlans.py | 3 +- netbox/ipam/models/vrfs.py | 6 ++- ...contact_name_alter_tenant_name_and_more.py | 29 +++++++++++ netbox/tenancy/models/contacts.py | 3 +- netbox/tenancy/models/tenants.py | 6 ++- ...6_alter_virtualmachine_options_and_more.py | 5 ++ netbox/virtualization/models/clusters.py | 3 +- ...cy_name_alter_ikeproposal_name_and_more.py | 49 +++++++++++++++++++ netbox/vpn/models/crypto.py | 15 ++++-- netbox/vpn/models/l2vpn.py | 3 +- netbox/vpn/models/tunnels.py | 3 +- .../0012_alter_wirelesslangroup_name.py | 19 +++++++ netbox/wireless/models.py | 3 +- 20 files changed, 224 insertions(+), 22 deletions(-) create mode 100644 netbox/circuits/migrations/0049_alter_provider_name_alter_providernetwork_name.py create mode 100644 netbox/ipam/migrations/0076_alter_asnrange_name_alter_routetarget_name_and_more.py create mode 100644 netbox/tenancy/migrations/0017_alter_contact_name_alter_tenant_name_and_more.py create mode 100644 netbox/vpn/migrations/0007_alter_ikepolicy_name_alter_ikeproposal_name_and_more.py create mode 100644 netbox/wireless/migrations/0012_alter_wirelesslangroup_name.py diff --git a/netbox/circuits/migrations/0049_alter_provider_name_alter_providernetwork_name.py b/netbox/circuits/migrations/0049_alter_provider_name_alter_providernetwork_name.py new file mode 100644 index 00000000000..ded72ae8fd6 --- /dev/null +++ b/netbox/circuits/migrations/0049_alter_provider_name_alter_providernetwork_name.py @@ -0,0 +1,24 @@ +# Generated by Django 5.0.9 on 2024-11-13 17:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('circuits', '0048_circuitterminations_cached_relations'), + ('dcim', '0197_natural_sort'), + ] + + operations = [ + migrations.AlterField( + model_name='provider', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=100, unique=True), + ), + migrations.AlterField( + model_name='providernetwork', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=100), + ), + ] diff --git a/netbox/circuits/models/providers.py b/netbox/circuits/models/providers.py index f0fe77b1acf..be81caa549f 100644 --- a/netbox/circuits/models/providers.py +++ b/netbox/circuits/models/providers.py @@ -21,7 +21,8 @@ class Provider(ContactsMixin, PrimaryModel): verbose_name=_('name'), max_length=100, unique=True, - help_text=_('Full name of the provider') + help_text=_('Full name of the provider'), + db_collation="natural_sort" ) slug = models.SlugField( verbose_name=_('slug'), @@ -95,7 +96,8 @@ class ProviderNetwork(PrimaryModel): """ name = models.CharField( verbose_name=_('name'), - max_length=100 + max_length=100, + db_collation="natural_sort" ) provider = models.ForeignKey( to='circuits.Provider', diff --git a/netbox/dcim/migrations/0197_natural_sort.py b/netbox/dcim/migrations/0197_natural_sort.py index 03e81e733bf..ccc7d1457fe 100644 --- a/netbox/dcim/migrations/0197_natural_sort.py +++ b/netbox/dcim/migrations/0197_natural_sort.py @@ -303,4 +303,24 @@ class Migration(migrations.Migration): 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), + ), ] diff --git a/netbox/dcim/models/devices.py b/netbox/dcim/models/devices.py index 2cb5ef4f32e..a836c5d373c 100644 --- a/netbox/dcim/models/devices.py +++ b/netbox/dcim/models/devices.py @@ -1315,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'), @@ -1377,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'), diff --git a/netbox/dcim/models/power.py b/netbox/dcim/models/power.py index d0c6b18b664..284cfe83254 100644 --- a/netbox/dcim/models/power.py +++ b/netbox/dcim/models/power.py @@ -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'), diff --git a/netbox/ipam/migrations/0076_alter_asnrange_name_alter_routetarget_name_and_more.py b/netbox/ipam/migrations/0076_alter_asnrange_name_alter_routetarget_name_and_more.py new file mode 100644 index 00000000000..40631331b3a --- /dev/null +++ b/netbox/ipam/migrations/0076_alter_asnrange_name_alter_routetarget_name_and_more.py @@ -0,0 +1,34 @@ +# Generated by Django 5.0.9 on 2024-11-13 17:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ipam', '0075_vlan_qinq'), + ('dcim', '0197_natural_sort'), + ] + + operations = [ + migrations.AlterField( + model_name='asnrange', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=100, unique=True), + ), + migrations.AlterField( + model_name='routetarget', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=21, unique=True), + ), + migrations.AlterField( + model_name='vlangroup', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=100), + ), + migrations.AlterField( + model_name='vrf', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=100), + ), + ] diff --git a/netbox/ipam/models/asns.py b/netbox/ipam/models/asns.py index eb47426b231..c1d25130128 100644 --- a/netbox/ipam/models/asns.py +++ b/netbox/ipam/models/asns.py @@ -16,7 +16,8 @@ class ASNRange(OrganizationalModel): name = models.CharField( verbose_name=_('name'), max_length=100, - unique=True + unique=True, + db_collation="natural_sort" ) slug = models.SlugField( verbose_name=_('slug'), diff --git a/netbox/ipam/models/vlans.py b/netbox/ipam/models/vlans.py index 7832cfc67c5..fa31fd60878 100644 --- a/netbox/ipam/models/vlans.py +++ b/netbox/ipam/models/vlans.py @@ -35,7 +35,8 @@ class VLANGroup(OrganizationalModel): """ name = models.CharField( verbose_name=_('name'), - max_length=100 + max_length=100, + db_collation="natural_sort" ) slug = models.SlugField( verbose_name=_('slug'), diff --git a/netbox/ipam/models/vrfs.py b/netbox/ipam/models/vrfs.py index 26afb7927ca..6a8b8d649b2 100644 --- a/netbox/ipam/models/vrfs.py +++ b/netbox/ipam/models/vrfs.py @@ -18,7 +18,8 @@ class VRF(PrimaryModel): """ name = models.CharField( verbose_name=_('name'), - max_length=100 + max_length=100, + db_collation="natural_sort" ) rd = models.CharField( max_length=VRF_RD_MAX_LENGTH, @@ -74,7 +75,8 @@ class RouteTarget(PrimaryModel): verbose_name=_('name'), max_length=VRF_RD_MAX_LENGTH, # Same format options as VRF RD (RFC 4360 section 4) unique=True, - help_text=_('Route target value (formatted in accordance with RFC 4360)') + help_text=_('Route target value (formatted in accordance with RFC 4360)'), + db_collation="natural_sort" ) tenant = models.ForeignKey( to='tenancy.Tenant', diff --git a/netbox/tenancy/migrations/0017_alter_contact_name_alter_tenant_name_and_more.py b/netbox/tenancy/migrations/0017_alter_contact_name_alter_tenant_name_and_more.py new file mode 100644 index 00000000000..5c0c9cd24c7 --- /dev/null +++ b/netbox/tenancy/migrations/0017_alter_contact_name_alter_tenant_name_and_more.py @@ -0,0 +1,29 @@ +# Generated by Django 5.0.9 on 2024-11-13 17:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('tenancy', '0016_charfield_null_choices'), + ('dcim', '0197_natural_sort'), + ] + + operations = [ + migrations.AlterField( + model_name='contact', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=100), + ), + migrations.AlterField( + model_name='tenant', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=100), + ), + migrations.AlterField( + model_name='tenantgroup', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=100, unique=True), + ), + ] diff --git a/netbox/tenancy/models/contacts.py b/netbox/tenancy/models/contacts.py index 24ffef0cf3c..3969c831757 100644 --- a/netbox/tenancy/models/contacts.py +++ b/netbox/tenancy/models/contacts.py @@ -56,7 +56,8 @@ class Contact(PrimaryModel): ) name = models.CharField( verbose_name=_('name'), - max_length=100 + max_length=100, + db_collation="natural_sort" ) title = models.CharField( verbose_name=_('title'), diff --git a/netbox/tenancy/models/tenants.py b/netbox/tenancy/models/tenants.py index 7a2d9c2f89b..55f0c5933cf 100644 --- a/netbox/tenancy/models/tenants.py +++ b/netbox/tenancy/models/tenants.py @@ -18,7 +18,8 @@ class TenantGroup(NestedGroupModel): name = models.CharField( verbose_name=_('name'), max_length=100, - unique=True + unique=True, + db_collation="natural_sort" ) slug = models.SlugField( verbose_name=_('slug'), @@ -39,7 +40,8 @@ class Tenant(ContactsMixin, PrimaryModel): """ name = models.CharField( verbose_name=_('name'), - max_length=100 + max_length=100, + db_collation="natural_sort" ) slug = models.SlugField( verbose_name=_('slug'), diff --git a/netbox/virtualization/migrations/0046_alter_virtualmachine_options_and_more.py b/netbox/virtualization/migrations/0046_alter_virtualmachine_options_and_more.py index 8114f73156a..1bb0771433a 100644 --- a/netbox/virtualization/migrations/0046_alter_virtualmachine_options_and_more.py +++ b/netbox/virtualization/migrations/0046_alter_virtualmachine_options_and_more.py @@ -34,4 +34,9 @@ class Migration(migrations.Migration): name='name', field=models.CharField(db_collation='natural_sort', max_length=64), ), + migrations.AlterField( + model_name='cluster', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=100), + ), ] diff --git a/netbox/virtualization/models/clusters.py b/netbox/virtualization/models/clusters.py index 601ee7f23ec..9f7b97e2983 100644 --- a/netbox/virtualization/models/clusters.py +++ b/netbox/virtualization/models/clusters.py @@ -50,7 +50,8 @@ class Cluster(ContactsMixin, CachedScopeMixin, PrimaryModel): """ name = models.CharField( verbose_name=_('name'), - max_length=100 + max_length=100, + db_collation="natural_sort" ) type = models.ForeignKey( verbose_name=_('type'), diff --git a/netbox/vpn/migrations/0007_alter_ikepolicy_name_alter_ikeproposal_name_and_more.py b/netbox/vpn/migrations/0007_alter_ikepolicy_name_alter_ikeproposal_name_and_more.py new file mode 100644 index 00000000000..a22eef1e536 --- /dev/null +++ b/netbox/vpn/migrations/0007_alter_ikepolicy_name_alter_ikeproposal_name_and_more.py @@ -0,0 +1,49 @@ +# Generated by Django 5.0.9 on 2024-11-13 17:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('vpn', '0006_charfield_null_choices'), + ('dcim', '0197_natural_sort'), + ] + + operations = [ + migrations.AlterField( + model_name='ikepolicy', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=100, unique=True), + ), + migrations.AlterField( + model_name='ikeproposal', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=100, unique=True), + ), + migrations.AlterField( + model_name='ipsecpolicy', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=100, unique=True), + ), + migrations.AlterField( + model_name='ipsecprofile', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=100, unique=True), + ), + migrations.AlterField( + model_name='ipsecproposal', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=100, unique=True), + ), + migrations.AlterField( + model_name='l2vpn', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=100, unique=True), + ), + migrations.AlterField( + model_name='tunnel', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=100, unique=True), + ), + ] diff --git a/netbox/vpn/models/crypto.py b/netbox/vpn/models/crypto.py index 2b721ec29b0..8e991b57869 100644 --- a/netbox/vpn/models/crypto.py +++ b/netbox/vpn/models/crypto.py @@ -22,7 +22,8 @@ class IKEProposal(PrimaryModel): name = models.CharField( verbose_name=_('name'), max_length=100, - unique=True + unique=True, + db_collation="natural_sort" ) authentication_method = models.CharField( verbose_name=('authentication method'), @@ -67,7 +68,8 @@ class IKEPolicy(PrimaryModel): name = models.CharField( verbose_name=_('name'), max_length=100, - unique=True + unique=True, + db_collation="natural_sort" ) version = models.PositiveSmallIntegerField( verbose_name=_('version'), @@ -125,7 +127,8 @@ class IPSecProposal(PrimaryModel): name = models.CharField( verbose_name=_('name'), max_length=100, - unique=True + unique=True, + db_collation="natural_sort" ) encryption_algorithm = models.CharField( verbose_name=_('encryption'), @@ -176,7 +179,8 @@ class IPSecPolicy(PrimaryModel): name = models.CharField( verbose_name=_('name'), max_length=100, - unique=True + unique=True, + db_collation="natural_sort" ) proposals = models.ManyToManyField( to='vpn.IPSecProposal', @@ -211,7 +215,8 @@ class IPSecProfile(PrimaryModel): name = models.CharField( verbose_name=_('name'), max_length=100, - unique=True + unique=True, + db_collation="natural_sort" ) mode = models.CharField( verbose_name=_('mode'), diff --git a/netbox/vpn/models/l2vpn.py b/netbox/vpn/models/l2vpn.py index b799ab32d3f..3e562531d42 100644 --- a/netbox/vpn/models/l2vpn.py +++ b/netbox/vpn/models/l2vpn.py @@ -20,7 +20,8 @@ class L2VPN(ContactsMixin, PrimaryModel): name = models.CharField( verbose_name=_('name'), max_length=100, - unique=True + unique=True, + db_collation="natural_sort" ) slug = models.SlugField( verbose_name=_('slug'), diff --git a/netbox/vpn/models/tunnels.py b/netbox/vpn/models/tunnels.py index 3a0f1dc1458..714024a81a3 100644 --- a/netbox/vpn/models/tunnels.py +++ b/netbox/vpn/models/tunnels.py @@ -31,7 +31,8 @@ class Tunnel(PrimaryModel): name = models.CharField( verbose_name=_('name'), max_length=100, - unique=True + unique=True, + db_collation="natural_sort" ) status = models.CharField( verbose_name=_('status'), diff --git a/netbox/wireless/migrations/0012_alter_wirelesslangroup_name.py b/netbox/wireless/migrations/0012_alter_wirelesslangroup_name.py new file mode 100644 index 00000000000..c776145e530 --- /dev/null +++ b/netbox/wireless/migrations/0012_alter_wirelesslangroup_name.py @@ -0,0 +1,19 @@ +# Generated by Django 5.0.9 on 2024-11-13 17:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('wireless', '0011_wirelesslan__location_wirelesslan__region_and_more'), + ('dcim', '0197_natural_sort'), + ] + + operations = [ + migrations.AlterField( + model_name='wirelesslangroup', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=100, unique=True), + ), + ] diff --git a/netbox/wireless/models.py b/netbox/wireless/models.py index d78c893a67d..61ff72bc1d3 100644 --- a/netbox/wireless/models.py +++ b/netbox/wireless/models.py @@ -52,7 +52,8 @@ class WirelessLANGroup(NestedGroupModel): name = models.CharField( verbose_name=_('name'), max_length=100, - unique=True + unique=True, + db_collation="natural_sort" ) slug = models.SlugField( verbose_name=_('slug'), From 39438a239a4a6c3d2f9209ecdc2a3d0573070761 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Date: Wed, 13 Nov 2024 09:55:24 -0800 Subject: [PATCH 05/10] 11279 fix tables /tests --- netbox/dcim/tables/devices.py | 11 ----------- netbox/dcim/tables/devicetypes.py | 4 +--- netbox/dcim/tables/racks.py | 1 - netbox/virtualization/tables/virtualmachines.py | 1 - 4 files changed, 1 insertion(+), 16 deletions(-) diff --git a/netbox/dcim/tables/devices.py b/netbox/dcim/tables/devices.py index fed33401c3e..41a45829ee1 100644 --- a/netbox/dcim/tables/devices.py +++ b/netbox/dcim/tables/devices.py @@ -132,7 +132,6 @@ class Meta(NetBoxTable.Meta): 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=' {{ value }}', - order_by=Accessor('_name'), attrs={'td': {'class': 'text-nowrap'}} ) actions = columns.ActionsColumn( @@ -433,7 +430,6 @@ class DeviceConsoleServerPortTable(ConsoleServerPortTable): verbose_name=_('Name'), template_code=' ' '{{ value }}', - order_by=Accessor('_name'), attrs={'td': {'class': 'text-nowrap'}} ) actions = columns.ActionsColumn( @@ -482,7 +478,6 @@ class DevicePowerPortTable(PowerPortTable): verbose_name=_('Name'), template_code=' ' '{{ value }}', - 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=' {{ value }}', - order_by=Accessor('_name'), attrs={'td': {'class': 'text-nowrap'}} ) actions = columns.ActionsColumn( @@ -736,7 +730,6 @@ class DeviceFrontPortTable(FrontPortTable): verbose_name=_('Name'), template_code=' ' '{{ value }}', - order_by=Accessor('_name'), attrs={'td': {'class': 'text-nowrap'}} ) actions = columns.ActionsColumn( @@ -783,7 +776,6 @@ class DeviceRearPortTable(RearPortTable): verbose_name=_('Name'), template_code=' ' '{{ value }}', - order_by=Accessor('_name'), attrs={'td': {'class': 'text-nowrap'}} ) actions = columns.ActionsColumn( @@ -846,7 +838,6 @@ class DeviceDeviceBayTable(DeviceBayTable): verbose_name=_('Name'), template_code=' {{ value }}', - order_by=Accessor('_name'), attrs={'td': {'class': 'text-nowrap'}} ) actions = columns.ActionsColumn( @@ -915,7 +906,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 +972,6 @@ class DeviceInventoryItemTable(InventoryItemTable): verbose_name=_('Name'), template_code='' '{{ value }}', - order_by=Accessor('_name'), attrs={'td': {'class': 'text-nowrap'}} ) diff --git a/netbox/dcim/tables/devicetypes.py b/netbox/dcim/tables/devicetypes.py index e8a4e35f114..d9e572556b7 100644 --- a/netbox/dcim/tables/devicetypes.py +++ b/netbox/dcim/tables/devicetypes.py @@ -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', ) diff --git a/netbox/dcim/tables/racks.py b/netbox/dcim/tables/racks.py index a6b704161af..dbd99ca246c 100644 --- a/netbox/dcim/tables/racks.py +++ b/netbox/dcim/tables/racks.py @@ -111,7 +111,6 @@ class Meta(NetBoxTable.Meta): class RackTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable): name = tables.Column( verbose_name=_('Name'), - order_by=('_name',), linkify=True ) location = tables.Column( diff --git a/netbox/virtualization/tables/virtualmachines.py b/netbox/virtualization/tables/virtualmachines.py index 4a31387114f..26d32f8cf09 100644 --- a/netbox/virtualization/tables/virtualmachines.py +++ b/netbox/virtualization/tables/virtualmachines.py @@ -53,7 +53,6 @@ class VirtualMachineTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable): name = tables.Column( verbose_name=_('Name'), - order_by=('_name',), linkify=True ) status = columns.ChoiceFieldColumn( From 23a22e7f1ca8e694cd58e06985587749a7fe6ea8 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Date: Wed, 13 Nov 2024 10:51:16 -0800 Subject: [PATCH 06/10] 11279 fix tests --- netbox/core/tests/test_changelog.py | 28 -------------------------- netbox/dcim/graphql/types.py | 20 +++++------------- netbox/dcim/views.py | 6 +++--- netbox/virtualization/graphql/types.py | 1 - 4 files changed, 8 insertions(+), 47 deletions(-) diff --git a/netbox/core/tests/test_changelog.py b/netbox/core/tests/test_changelog.py index c58968ee8ab..4914dbaf37a 100644 --- a/netbox/core/tests/test_changelog.py +++ b/netbox/core/tests/test_changelog.py @@ -76,10 +76,6 @@ def test_create_object(self): self.assertEqual(oc.postchange_data['custom_fields']['cf2'], form_data['cf_cf2']) self.assertEqual(oc.postchange_data['tags'], ['Tag 1', 'Tag 2']) - # Check that private attributes were included in raw data but not display data - self.assertIn('_name', oc.postchange_data) - self.assertNotIn('_name', oc.postchange_data_clean) - def test_update_object(self): site = Site(name='Site 1', slug='site-1') site.save() @@ -117,12 +113,6 @@ def test_update_object(self): self.assertEqual(oc.postchange_data['custom_fields']['cf2'], form_data['cf_cf2']) self.assertEqual(oc.postchange_data['tags'], ['Tag 3']) - # Check that private attributes were included in raw data but not display data - self.assertIn('_name', oc.prechange_data) - self.assertNotIn('_name', oc.prechange_data_clean) - self.assertIn('_name', oc.postchange_data) - self.assertNotIn('_name', oc.postchange_data_clean) - def test_delete_object(self): site = Site( name='Site 1', @@ -153,10 +143,6 @@ def test_delete_object(self): self.assertEqual(oc.prechange_data['tags'], ['Tag 1', 'Tag 2']) self.assertEqual(oc.postchange_data, None) - # Check that private attributes were included in raw data but not display data - self.assertIn('_name', oc.prechange_data) - self.assertNotIn('_name', oc.prechange_data_clean) - def test_bulk_update_objects(self): sites = ( Site(name='Site 1', slug='site-1', status=SiteStatusChoices.STATUS_ACTIVE), @@ -353,10 +339,6 @@ def test_create_object(self): self.assertEqual(oc.postchange_data['custom_fields'], data['custom_fields']) self.assertEqual(oc.postchange_data['tags'], ['Tag 1', 'Tag 2']) - # Check that private attributes were included in raw data but not display data - self.assertIn('_name', oc.postchange_data) - self.assertNotIn('_name', oc.postchange_data_clean) - def test_update_object(self): site = Site(name='Site 1', slug='site-1') site.save() @@ -389,12 +371,6 @@ def test_update_object(self): self.assertEqual(oc.postchange_data['custom_fields'], data['custom_fields']) self.assertEqual(oc.postchange_data['tags'], ['Tag 3']) - # Check that private attributes were included in raw data but not display data - self.assertIn('_name', oc.prechange_data) - self.assertNotIn('_name', oc.prechange_data_clean) - self.assertIn('_name', oc.postchange_data) - self.assertNotIn('_name', oc.postchange_data_clean) - def test_delete_object(self): site = Site( name='Site 1', @@ -423,10 +399,6 @@ def test_delete_object(self): self.assertEqual(oc.prechange_data['tags'], ['Tag 1', 'Tag 2']) self.assertEqual(oc.postchange_data, None) - # Check that private attributes were included in raw data but not display data - self.assertIn('_name', oc.prechange_data) - self.assertNotIn('_name', oc.prechange_data_clean) - def test_bulk_create_objects(self): data = ( { diff --git a/netbox/dcim/graphql/types.py b/netbox/dcim/graphql/types.py index 6493ec6b1e3..fc5f35780c3 100644 --- a/netbox/dcim/graphql/types.py +++ b/netbox/dcim/graphql/types.py @@ -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 @@ def parent(self) -> Annotated["ModuleBayType", strawberry.lazy('dcim.graphql.typ 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 @@ def circuit_terminations(self) -> List[Annotated["CircuitTerminationType", straw 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 diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 9a821a3843e..03915386e9d 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -688,7 +688,7 @@ def get(self, request): sort = request.GET.get('sort', 'name') if sort not in ORDERING_CHOICES: sort = 'name' - sort_field = sort.replace("name", "_name") # Use natural ordering + sort_field = sort # Use natural ordering racks = racks.order_by(sort_field) # Pagination @@ -731,8 +731,8 @@ def get_extra_context(self, request, instance): 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([ diff --git a/netbox/virtualization/graphql/types.py b/netbox/virtualization/graphql/types.py index 6052c8936ae..f405705fb6c 100644 --- a/netbox/virtualization/graphql/types.py +++ b/netbox/virtualization/graphql/types.py @@ -77,7 +77,6 @@ class ClusterTypeType(OrganizationalObjectType): filters=VirtualMachineFilter ) class VirtualMachineType(ConfigContextMixin, ContactsMixin, NetBoxObjectType): - _name: str interface_count: BigInt virtual_disk_count: BigInt interface_count: BigInt From 973c410db212549fe3e335930f676988cd3599b0 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Date: Wed, 13 Nov 2024 12:11:35 -0800 Subject: [PATCH 07/10] 11279 refactor VirtualDisk --- netbox/virtualization/graphql/types.py | 2 +- ...6_alter_virtualmachine_options_and_more.py | 13 +++++---- .../virtualization/models/virtualmachines.py | 29 +++++++++++-------- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/netbox/virtualization/graphql/types.py b/netbox/virtualization/graphql/types.py index f405705fb6c..8476eac7e66 100644 --- a/netbox/virtualization/graphql/types.py +++ b/netbox/virtualization/graphql/types.py @@ -25,7 +25,6 @@ class ComponentType(NetBoxObjectType): """ Base type for device/VM components """ - _name: str virtual_machine: Annotated["VirtualMachineType", strawberry.lazy('virtualization.graphql.types')] @@ -101,6 +100,7 @@ class VirtualMachineType(ConfigContextMixin, ContactsMixin, NetBoxObjectType): filters=VMInterfaceFilter ) class VMInterfaceType(IPAddressesMixin, ComponentType): + _name: str mac_address: str | None parent: Annotated["VMInterfaceType", strawberry.lazy('virtualization.graphql.types')] | None bridge: Annotated["VMInterfaceType", strawberry.lazy('virtualization.graphql.types')] | None diff --git a/netbox/virtualization/migrations/0046_alter_virtualmachine_options_and_more.py b/netbox/virtualization/migrations/0046_alter_virtualmachine_options_and_more.py index 1bb0771433a..a8080d540c5 100644 --- a/netbox/virtualization/migrations/0046_alter_virtualmachine_options_and_more.py +++ b/netbox/virtualization/migrations/0046_alter_virtualmachine_options_and_more.py @@ -15,6 +15,10 @@ class Migration(migrations.Migration): name='virtualmachine', options={'ordering': ('name', 'pk')}, ), + migrations.AlterModelOptions( + name='virtualdisk', + options={'ordering': ('virtual_machine', 'name')}, + ), migrations.RemoveField( model_name='virtualmachine', name='_name', @@ -29,14 +33,13 @@ class Migration(migrations.Migration): name='name', field=models.CharField(db_collation='natural_sort', max_length=64), ), - migrations.AlterField( - model_name='vminterface', - name='name', - field=models.CharField(db_collation='natural_sort', max_length=64), - ), migrations.AlterField( model_name='cluster', name='name', field=models.CharField(db_collation='natural_sort', max_length=100), ), + migrations.RemoveField( + model_name='virtualdisk', + name='_name', + ), ] diff --git a/netbox/virtualization/models/virtualmachines.py b/netbox/virtualization/models/virtualmachines.py index c83d76f02b9..7e048b950f8 100644 --- a/netbox/virtualization/models/virtualmachines.py +++ b/netbox/virtualization/models/virtualmachines.py @@ -267,17 +267,6 @@ class ComponentModel(NetBoxModel): on_delete=models.CASCADE, related_name='%(class)ss' ) - name = models.CharField( - verbose_name=_('name'), - max_length=64, - db_collation="natural_sort" - ) - _name = NaturalOrderingField( - target_field='name', - naturalize_function=naturalize_interface, - max_length=100, - blank=True - ) description = models.CharField( verbose_name=_('description'), max_length=200, @@ -286,7 +275,6 @@ class ComponentModel(NetBoxModel): class Meta: abstract = True - ordering = ('virtual_machine', CollateAsChar('_name')) constraints = ( models.UniqueConstraint( fields=('virtual_machine', 'name'), @@ -308,6 +296,16 @@ def parent_object(self): class VMInterface(ComponentModel, BaseInterface, TrackingModelMixin): + name = models.CharField( + verbose_name=_('name'), + max_length=64, + ) + _name = NaturalOrderingField( + target_field='name', + naturalize_function=naturalize_interface, + max_length=100, + blank=True + ) virtual_machine = models.ForeignKey( to='virtualization.VirtualMachine', on_delete=models.CASCADE, @@ -355,6 +353,7 @@ class VMInterface(ComponentModel, BaseInterface, TrackingModelMixin): class Meta(ComponentModel.Meta): verbose_name = _('interface') verbose_name_plural = _('interfaces') + ordering = ('virtual_machine', CollateAsChar('_name')) def clean(self): super().clean() @@ -406,6 +405,11 @@ def l2vpn_termination(self): class VirtualDisk(ComponentModel, TrackingModelMixin): + name = models.CharField( + verbose_name=_('name'), + max_length=64, + db_collation="natural_sort" + ) size = models.PositiveIntegerField( verbose_name=_('size (MB)'), ) @@ -413,3 +417,4 @@ class VirtualDisk(ComponentModel, TrackingModelMixin): class Meta(ComponentModel.Meta): verbose_name = _('virtual disk') verbose_name_plural = _('virtual disks') + ordering = ('virtual_machine', 'name') From d1802bff0b43636dc3ac4f440b66774f057adbb8 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 15 Nov 2024 08:26:13 -0500 Subject: [PATCH 08/10] Clean up migrations --- ...etwork_name.py => 0049_natural_ordering.py} | 4 +--- .../migrations/0197_natural_sort_collation.py | 17 +++++++++++++++++ ...atural_sort.py => 0198_natural_ordering.py} | 10 +--------- ...me_and_more.py => 0076_natural_ordering.py} | 4 +--- .../project-static/src/buttons/launchModal.ts | 18 ++++++++++++++++++ ...me_and_more.py => 0017_natural_ordering.py} | 4 +--- ...ns_and_more.py => 0046_natural_ordering.py} | 4 +--- ...me_and_more.py => 0007_natural_ordering.py} | 4 +--- ...ngroup_name.py => 0012_natural_ordering.py} | 4 +--- 9 files changed, 42 insertions(+), 27 deletions(-) rename netbox/circuits/migrations/{0049_alter_provider_name_alter_providernetwork_name.py => 0049_natural_ordering.py} (87%) create mode 100644 netbox/dcim/migrations/0197_natural_sort_collation.py rename netbox/dcim/migrations/{0197_natural_sort.py => 0198_natural_ordering.py} (97%) rename netbox/ipam/migrations/{0076_alter_asnrange_name_alter_routetarget_name_and_more.py => 0076_natural_ordering.py} (91%) create mode 100644 netbox/project-static/src/buttons/launchModal.ts rename netbox/tenancy/migrations/{0017_alter_contact_name_alter_tenant_name_and_more.py => 0017_natural_ordering.py} (89%) rename netbox/virtualization/migrations/{0046_alter_virtualmachine_options_and_more.py => 0046_natural_ordering.py} (93%) rename netbox/vpn/migrations/{0007_alter_ikepolicy_name_alter_ikeproposal_name_and_more.py => 0007_natural_ordering.py} (94%) rename netbox/wireless/migrations/{0012_alter_wirelesslangroup_name.py => 0012_natural_ordering.py} (82%) diff --git a/netbox/circuits/migrations/0049_alter_provider_name_alter_providernetwork_name.py b/netbox/circuits/migrations/0049_natural_ordering.py similarity index 87% rename from netbox/circuits/migrations/0049_alter_provider_name_alter_providernetwork_name.py rename to netbox/circuits/migrations/0049_natural_ordering.py index ded72ae8fd6..1b4f565e84c 100644 --- a/netbox/circuits/migrations/0049_alter_provider_name_alter_providernetwork_name.py +++ b/netbox/circuits/migrations/0049_natural_ordering.py @@ -1,5 +1,3 @@ -# Generated by Django 5.0.9 on 2024-11-13 17:15 - from django.db import migrations, models @@ -7,7 +5,7 @@ class Migration(migrations.Migration): dependencies = [ ('circuits', '0048_circuitterminations_cached_relations'), - ('dcim', '0197_natural_sort'), + ('dcim', '0197_natural_sort_collation'), ] operations = [ diff --git a/netbox/dcim/migrations/0197_natural_sort_collation.py b/netbox/dcim/migrations/0197_natural_sort_collation.py new file mode 100644 index 00000000000..a77632b37c9 --- /dev/null +++ b/netbox/dcim/migrations/0197_natural_sort_collation.py @@ -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", + ), + ] diff --git a/netbox/dcim/migrations/0197_natural_sort.py b/netbox/dcim/migrations/0198_natural_ordering.py similarity index 97% rename from netbox/dcim/migrations/0197_natural_sort.py rename to netbox/dcim/migrations/0198_natural_ordering.py index ccc7d1457fe..83e94a1951f 100644 --- a/netbox/dcim/migrations/0197_natural_sort.py +++ b/netbox/dcim/migrations/0198_natural_ordering.py @@ -1,21 +1,13 @@ -# Generated by Django 5.0.9 on 2024-11-12 22:21 - -from django.contrib.postgres.operations import CreateCollation from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('dcim', '0196_qinq_svlan'), + ('dcim', '0197_natural_sort_collation'), ] operations = [ - CreateCollation( - "natural_sort", - provider="icu", - locale="und-u-kn-true", - ), migrations.AlterModelOptions( name='site', options={'ordering': ('name',)}, diff --git a/netbox/ipam/migrations/0076_alter_asnrange_name_alter_routetarget_name_and_more.py b/netbox/ipam/migrations/0076_natural_ordering.py similarity index 91% rename from netbox/ipam/migrations/0076_alter_asnrange_name_alter_routetarget_name_and_more.py rename to netbox/ipam/migrations/0076_natural_ordering.py index 40631331b3a..8c7bfaea1b7 100644 --- a/netbox/ipam/migrations/0076_alter_asnrange_name_alter_routetarget_name_and_more.py +++ b/netbox/ipam/migrations/0076_natural_ordering.py @@ -1,5 +1,3 @@ -# Generated by Django 5.0.9 on 2024-11-13 17:15 - from django.db import migrations, models @@ -7,7 +5,7 @@ class Migration(migrations.Migration): dependencies = [ ('ipam', '0075_vlan_qinq'), - ('dcim', '0197_natural_sort'), + ('dcim', '0197_natural_sort_collation'), ] operations = [ diff --git a/netbox/project-static/src/buttons/launchModal.ts b/netbox/project-static/src/buttons/launchModal.ts new file mode 100644 index 00000000000..dd4e769ad91 --- /dev/null +++ b/netbox/project-static/src/buttons/launchModal.ts @@ -0,0 +1,18 @@ +import { getElements } from '../util'; +import { Modal } from 'bootstrap'; + +export function initLaunchModal(): void { + console.log('initLaunchModal()'); + const modal_element = document.getElementById('htmx-modal'); + if (modal_element == null) return; + console.log('found modal element'); + const modal = new Modal(modal_element); + console.log('created modal'); + + for (const launchButton of getElements('button.launch-htmx-modal')) { + console.log(`found button: {launchButton}`); + launchButton.addEventListener('click', () => { + modal.show(); + }); + } +} diff --git a/netbox/tenancy/migrations/0017_alter_contact_name_alter_tenant_name_and_more.py b/netbox/tenancy/migrations/0017_natural_ordering.py similarity index 89% rename from netbox/tenancy/migrations/0017_alter_contact_name_alter_tenant_name_and_more.py rename to netbox/tenancy/migrations/0017_natural_ordering.py index 5c0c9cd24c7..de1fb49aac5 100644 --- a/netbox/tenancy/migrations/0017_alter_contact_name_alter_tenant_name_and_more.py +++ b/netbox/tenancy/migrations/0017_natural_ordering.py @@ -1,5 +1,3 @@ -# Generated by Django 5.0.9 on 2024-11-13 17:15 - from django.db import migrations, models @@ -7,7 +5,7 @@ class Migration(migrations.Migration): dependencies = [ ('tenancy', '0016_charfield_null_choices'), - ('dcim', '0197_natural_sort'), + ('dcim', '0197_natural_sort_collation'), ] operations = [ diff --git a/netbox/virtualization/migrations/0046_alter_virtualmachine_options_and_more.py b/netbox/virtualization/migrations/0046_natural_ordering.py similarity index 93% rename from netbox/virtualization/migrations/0046_alter_virtualmachine_options_and_more.py rename to netbox/virtualization/migrations/0046_natural_ordering.py index a8080d540c5..9284b633126 100644 --- a/netbox/virtualization/migrations/0046_alter_virtualmachine_options_and_more.py +++ b/netbox/virtualization/migrations/0046_natural_ordering.py @@ -1,5 +1,3 @@ -# Generated by Django 5.0.9 on 2024-11-13 16:54 - from django.db import migrations, models @@ -7,7 +5,7 @@ class Migration(migrations.Migration): dependencies = [ ('virtualization', '0045_clusters_cached_relations'), - ('dcim', '0197_natural_sort'), + ('dcim', '0197_natural_sort_collation'), ] operations = [ diff --git a/netbox/vpn/migrations/0007_alter_ikepolicy_name_alter_ikeproposal_name_and_more.py b/netbox/vpn/migrations/0007_natural_ordering.py similarity index 94% rename from netbox/vpn/migrations/0007_alter_ikepolicy_name_alter_ikeproposal_name_and_more.py rename to netbox/vpn/migrations/0007_natural_ordering.py index a22eef1e536..01dd4620f8d 100644 --- a/netbox/vpn/migrations/0007_alter_ikepolicy_name_alter_ikeproposal_name_and_more.py +++ b/netbox/vpn/migrations/0007_natural_ordering.py @@ -1,5 +1,3 @@ -# Generated by Django 5.0.9 on 2024-11-13 17:15 - from django.db import migrations, models @@ -7,7 +5,7 @@ class Migration(migrations.Migration): dependencies = [ ('vpn', '0006_charfield_null_choices'), - ('dcim', '0197_natural_sort'), + ('dcim', '0197_natural_sort_collation'), ] operations = [ diff --git a/netbox/wireless/migrations/0012_alter_wirelesslangroup_name.py b/netbox/wireless/migrations/0012_natural_ordering.py similarity index 82% rename from netbox/wireless/migrations/0012_alter_wirelesslangroup_name.py rename to netbox/wireless/migrations/0012_natural_ordering.py index c776145e530..da818bdd942 100644 --- a/netbox/wireless/migrations/0012_alter_wirelesslangroup_name.py +++ b/netbox/wireless/migrations/0012_natural_ordering.py @@ -1,5 +1,3 @@ -# Generated by Django 5.0.9 on 2024-11-13 17:15 - from django.db import migrations, models @@ -7,7 +5,7 @@ class Migration(migrations.Migration): dependencies = [ ('wireless', '0011_wirelesslan__location_wirelesslan__region_and_more'), - ('dcim', '0197_natural_sort'), + ('dcim', '0197_natural_sort_collation'), ] operations = [ From 8a42c72ca46d36bc0e41c78855a9ae82a98efaa0 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 15 Nov 2024 09:04:52 -0500 Subject: [PATCH 09/10] Misc cleanup --- netbox/dcim/tables/devices.py | 7 ++++++- netbox/dcim/tables/devicetypes.py | 4 ++++ netbox/dcim/views.py | 3 +-- netbox/utilities/fields.py | 3 +-- netbox/virtualization/models/virtualmachines.py | 16 +++++----------- 5 files changed, 17 insertions(+), 16 deletions(-) diff --git a/netbox/dcim/tables/devices.py b/netbox/dcim/tables/devices.py index 41a45829ee1..b7634626d14 100644 --- a/netbox/dcim/tables/devices.py +++ b/netbox/dcim/tables/devices.py @@ -544,6 +544,11 @@ class Meta(CableTerminationTable.Meta, DeviceComponentTable.Meta): class BaseInterfaceTable(NetBoxTable): + name = tables.Column( + verbose_name=_('Name'), + linkify=True, + order_by=('_name',) + ) enabled = columns.BooleanColumn( verbose_name=_('Enabled'), ) @@ -591,7 +596,7 @@ def value_tagged_vlans(self, value): 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={ diff --git a/netbox/dcim/tables/devicetypes.py b/netbox/dcim/tables/devicetypes.py index d9e572556b7..a7f8f08e87f 100644 --- a/netbox/dcim/tables/devicetypes.py +++ b/netbox/dcim/tables/devicetypes.py @@ -218,6 +218,10 @@ class Meta(ComponentTemplateTable.Meta): class InterfaceTemplateTable(ComponentTemplateTable): + name = tables.Column( + verbose_name=_('Name'), + order_by=('_name',) + ) enabled = columns.BooleanColumn( verbose_name=_('Enabled'), ) diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 03915386e9d..7a5a771a94a 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -688,8 +688,7 @@ def get(self, request): sort = request.GET.get('sort', 'name') if sort not in ORDERING_CHOICES: sort = 'name' - sort_field = sort # Use natural ordering - racks = racks.order_by(sort_field) + racks = racks.order_by(sort) # Pagination per_page = get_paginate_count(request) diff --git a/netbox/utilities/fields.py b/netbox/utilities/fields.py index c4ea13bc9f5..1d16a1d3fde 100644 --- a/netbox/utilities/fields.py +++ b/netbox/utilities/fields.py @@ -5,7 +5,6 @@ from django.utils.safestring import mark_safe from django.utils.translation import gettext_lazy as _ -from utilities.ordering import naturalize_interface from .forms.widgets import ColorSelect from .validators import ColorValidator @@ -40,7 +39,7 @@ class NaturalOrderingField(models.CharField): """ description = "Stores a representation of its target field suitable for natural ordering" - def __init__(self, target_field, naturalize_function=naturalize_interface, *args, **kwargs): + def __init__(self, target_field, naturalize_function, *args, **kwargs): self.target_field = target_field self.naturalize_function = naturalize_function super().__init__(*args, **kwargs) diff --git a/netbox/virtualization/models/virtualmachines.py b/netbox/virtualization/models/virtualmachines.py index 7e048b950f8..ebfb2d6c50a 100644 --- a/netbox/virtualization/models/virtualmachines.py +++ b/netbox/virtualization/models/virtualmachines.py @@ -267,6 +267,11 @@ class ComponentModel(NetBoxModel): on_delete=models.CASCADE, related_name='%(class)ss' ) + name = models.CharField( + verbose_name=_('name'), + max_length=64, + db_collation="natural_sort" + ) description = models.CharField( verbose_name=_('description'), max_length=200, @@ -311,12 +316,6 @@ class VMInterface(ComponentModel, BaseInterface, TrackingModelMixin): on_delete=models.CASCADE, related_name='interfaces' # Override ComponentModel ) - _name = NaturalOrderingField( - target_field='name', - naturalize_function=naturalize_interface, - max_length=100, - blank=True - ) ip_addresses = GenericRelation( to='ipam.IPAddress', content_type_field='assigned_object_type', @@ -405,11 +404,6 @@ def l2vpn_termination(self): class VirtualDisk(ComponentModel, TrackingModelMixin): - name = models.CharField( - verbose_name=_('name'), - max_length=64, - db_collation="natural_sort" - ) size = models.PositiveIntegerField( verbose_name=_('size (MB)'), ) From baa4142f84ac2ec383cdde056cc72ba2ae7d8a10 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 15 Nov 2024 09:13:38 -0500 Subject: [PATCH 10/10] Correct errant file inclusion --- .../project-static/src/buttons/launchModal.ts | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 netbox/project-static/src/buttons/launchModal.ts diff --git a/netbox/project-static/src/buttons/launchModal.ts b/netbox/project-static/src/buttons/launchModal.ts deleted file mode 100644 index dd4e769ad91..00000000000 --- a/netbox/project-static/src/buttons/launchModal.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { getElements } from '../util'; -import { Modal } from 'bootstrap'; - -export function initLaunchModal(): void { - console.log('initLaunchModal()'); - const modal_element = document.getElementById('htmx-modal'); - if (modal_element == null) return; - console.log('found modal element'); - const modal = new Modal(modal_element); - console.log('created modal'); - - for (const launchButton of getElements('button.launch-htmx-modal')) { - console.log(`found button: {launchButton}`); - launchButton.addEventListener('click', () => { - modal.show(); - }); - } -}