mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-22 20:12:00 -06:00
Introduce NaturalOrderingField
This commit is contained in:
parent
b3c2b78e8a
commit
b271fd32bd
@ -1,6 +1,7 @@
|
||||
from django.core.validators import RegexValidator
|
||||
from django.db import models
|
||||
|
||||
from utilities.ordering import naturalize
|
||||
from .forms import ColorSelect
|
||||
|
||||
ColorValidator = RegexValidator(
|
||||
@ -35,3 +36,35 @@ class ColorField(models.CharField):
|
||||
def formfield(self, **kwargs):
|
||||
kwargs['widget'] = ColorSelect
|
||||
return super().formfield(**kwargs)
|
||||
|
||||
|
||||
class NaturalOrderingField(models.CharField):
|
||||
"""
|
||||
A field which stores a naturalized representation of its target field, to be used for ordering its parent model.
|
||||
|
||||
:param target_field: Name of the field of the parent model to be naturalized
|
||||
:param naturalize_function: The function used to generate a naturalized value (optional)
|
||||
"""
|
||||
description = "Stores a representation of its target field suitable for natural ordering"
|
||||
|
||||
def __init__(self, target_field, naturalize_function=naturalize, *args, **kwargs):
|
||||
self.target_field = target_field
|
||||
self.naturalize_function = naturalize_function
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def pre_save(self, model_instance, add):
|
||||
"""
|
||||
Generate a naturalized value from the target field
|
||||
"""
|
||||
value = getattr(model_instance, self.target_field)
|
||||
return self.naturalize_function(value, max_length=self.max_length)
|
||||
|
||||
def deconstruct(self):
|
||||
kwargs = super().deconstruct()[3] # Pass kwargs from CharField
|
||||
kwargs['naturalize_function'] = self.naturalize_function
|
||||
return (
|
||||
self.name,
|
||||
'utilities.fields.NaturalOrderingField',
|
||||
['target_field'],
|
||||
kwargs,
|
||||
)
|
||||
|
31
netbox/utilities/ordering.py
Normal file
31
netbox/utilities/ordering.py
Normal file
@ -0,0 +1,31 @@
|
||||
import re
|
||||
|
||||
|
||||
def naturalize(value, max_length=None, integer_places=8):
|
||||
"""
|
||||
Take an alphanumeric string and prepend all integers to `integer_places` places to ensure the strings
|
||||
are ordered naturally. For example:
|
||||
|
||||
site9router21
|
||||
site10router4
|
||||
site10router19
|
||||
|
||||
becomes:
|
||||
|
||||
site00000009router00000021
|
||||
site00000010router00000004
|
||||
site00000010router00000019
|
||||
|
||||
:param value: The value to be naturalized
|
||||
:param max_length: The maximum length of the returned string. Characters beyond this length will be stripped.
|
||||
:param integer_places: The number of places to which each integer will be expanded. (Default: 8)
|
||||
"""
|
||||
output = []
|
||||
for segment in re.split(r'(\d+)', value):
|
||||
if segment.isdigit():
|
||||
output.append(segment.rjust(integer_places, '0'))
|
||||
elif segment:
|
||||
output.append(segment)
|
||||
ret = ''.join(output)
|
||||
|
||||
return ret[:max_length] if max_length else ret
|
Loading…
Reference in New Issue
Block a user