diff --git a/netbox/dcim/models.py b/netbox/dcim/models.py index 2d7e0549a..be1aca7f0 100644 --- a/netbox/dcim/models.py +++ b/netbox/dcim/models.py @@ -17,7 +17,7 @@ from timezone_field import TimeZoneField from extras.models import ConfigContextModel, CustomFieldModel, ObjectChange from utilities.fields import ColorField, NullableCharField -from utilities.managers import NaturalOrderByManager +from utilities.managers import NaturalOrderingManager from utilities.models import ChangeLoggedModel from utilities.utils import serialize_object, to_meters from .constants import * @@ -179,10 +179,6 @@ class Region(MPTTModel, ChangeLoggedModel): # Sites # -class SiteManager(NaturalOrderByManager): - natural_order_field = 'name' - - class Site(ChangeLoggedModel, CustomFieldModel): """ A Site represents a geographic location within a network; typically a building or campus. The optional facility @@ -273,7 +269,7 @@ class Site(ChangeLoggedModel, CustomFieldModel): to='extras.ImageAttachment' ) - objects = SiteManager() + objects = NaturalOrderingManager() tags = TaggableManager() csv_headers = [ @@ -416,10 +412,6 @@ class RackRole(ChangeLoggedModel): ) -class RackManager(NaturalOrderByManager): - natural_order_field = 'name' - - class Rack(ChangeLoggedModel, CustomFieldModel): """ Devices are housed within Racks. Each rack has a defined height measured in rack units, and a front and rear face. @@ -524,7 +516,7 @@ class Rack(ChangeLoggedModel, CustomFieldModel): to='extras.ImageAttachment' ) - objects = RackManager() + objects = NaturalOrderingManager() tags = TaggableManager() csv_headers = [ @@ -1278,10 +1270,6 @@ class Platform(ChangeLoggedModel): ) -class DeviceManager(NaturalOrderByManager): - natural_order_field = 'name' - - class Device(ChangeLoggedModel, ConfigContextModel, CustomFieldModel): """ A Device represents a piece of physical hardware mounted within a Rack. Each Device is assigned a DeviceType, @@ -1419,7 +1407,7 @@ class Device(ChangeLoggedModel, ConfigContextModel, CustomFieldModel): to='extras.ImageAttachment' ) - objects = DeviceManager() + objects = NaturalOrderingManager() tags = TaggableManager() csv_headers = [ diff --git a/netbox/utilities/managers.py b/netbox/utilities/managers.py index da4117594..998e27a8c 100644 --- a/netbox/utilities/managers.py +++ b/netbox/utilities/managers.py @@ -1,26 +1,30 @@ from django.db.models import Manager +NAT1 = r"CAST(SUBSTRING({}.{} FROM '^(\d{{1,9}})') AS integer)" +NAT2 = r"SUBSTRING({}.{} FROM '^\d*(.*?)\d*$')" +NAT3 = r"CAST(SUBSTRING({}.{} FROM '(\d{{1,9}})$') AS integer)" -class NaturalOrderByManager(Manager): + +class NaturalOrderingManager(Manager): """ - Order objects naturally by a designated field. Leading and/or trailing digits of values within this field will be - cast as independent integers and sorted accordingly. For example, "Foo2" will be ordered before "Foo10", even though - the digit 1 is normally ordered before the digit 2. + Order objects naturally by a designated field (defaults to 'name'). Leading and/or trailing digits of values within + this field will be cast as independent integers and sorted accordingly. For example, "Foo2" will be ordered before + "Foo10", even though the digit 1 is normally ordered before the digit 2. """ - natural_order_field = None + natural_order_field = 'name' def get_queryset(self): - queryset = super(NaturalOrderByManager, self).get_queryset() + queryset = super(NaturalOrderingManager, self).get_queryset() db_table = self.model._meta.db_table db_field = self.natural_order_field # Append the three subfields derived from the designated natural ordering field queryset = queryset.extra(select={ - '_nat1': r"CAST(SUBSTRING({}.{} FROM '^(\d{{1,9}})') AS integer)".format(db_table, db_field), - '_nat2': r"SUBSTRING({}.{} FROM '^\d*(.*?)\d*$')".format(db_table, db_field), - '_nat3': r"CAST(SUBSTRING({}.{} FROM '(\d{{1,9}})$') AS integer)".format(db_table, db_field), + '_nat1': NAT1.format(db_table, db_field), + '_nat2': NAT2.format(db_table, db_field), + '_nat3': NAT3.format(db_table, db_field), }) # Replace any instance of the designated natural ordering field with its three subfields