mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-09 00:58:16 -06:00
9627 change to NumericArrayField
This commit is contained in:
parent
3c89651076
commit
72ed36fd5b
@ -12,7 +12,6 @@ from tenancy.models import Tenant
|
||||
from utilities.forms import add_blank_choice
|
||||
from utilities.forms.fields import (
|
||||
CommentField, ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, NumericArrayField,
|
||||
NumericRangeArrayField,
|
||||
)
|
||||
from utilities.forms.rendering import FieldSet
|
||||
from utilities.forms.widgets import BulkEditNullBooleanSelect
|
||||
@ -472,13 +471,16 @@ class VLANGroupBulkEditForm(NetBoxModelBulkEditForm):
|
||||
'group_id': '$clustergroup',
|
||||
}
|
||||
)
|
||||
vlan_id_ranges = NumericRangeArrayField(
|
||||
allowed_vids = NumericArrayField(
|
||||
required=False,
|
||||
label=_('min/max VLAN IDs'),
|
||||
base_field=forms.IntegerField(),
|
||||
help_text=_('Comma-separated list of numeric VLAN IDs. A range may be specified using a hyphen.'),
|
||||
)
|
||||
|
||||
model = VLANGroup
|
||||
fieldsets = (
|
||||
FieldSet('site', 'vlan_id_ranges', 'description'),
|
||||
FieldSet('site', 'allowed_vids', 'description'),
|
||||
FieldSet(
|
||||
'scope_type', 'region', 'sitegroup', 'site', 'location', 'rack', 'clustergroup', 'cluster', name=_('Scope')
|
||||
),
|
||||
|
@ -10,7 +10,7 @@ from netbox.forms import NetBoxModelImportForm
|
||||
from tenancy.models import Tenant
|
||||
from utilities.forms.fields import (
|
||||
CSVChoiceField, CSVContentTypeField, CSVModelChoiceField, CSVModelMultipleChoiceField, SlugField,
|
||||
NumericRangeArrayField,
|
||||
NumericArrayField,
|
||||
)
|
||||
from virtualization.models import VirtualMachine, VMInterface
|
||||
|
||||
@ -412,13 +412,16 @@ class VLANGroupImportForm(NetBoxModelImportForm):
|
||||
required=False,
|
||||
label=_('Scope type (app & model)')
|
||||
)
|
||||
vlan_id_ranges = NumericRangeArrayField(
|
||||
allowed_vids = NumericArrayField(
|
||||
required=False,
|
||||
label=_('min/max VLAN IDs'),
|
||||
base_field=forms.IntegerField(),
|
||||
help_text=_('Comma-separated list of numeric VLAN IDs. A range may be specified using a hyphen.'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = VLANGroup
|
||||
fields = ('name', 'slug', 'scope_type', 'scope_id', 'vlan_id_ranges', 'description', 'tags')
|
||||
fields = ('name', 'slug', 'scope_type', 'scope_id', 'allowed_vids', 'description', 'tags')
|
||||
labels = {
|
||||
'scope_id': 'Scope ID',
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ from utilities.exceptions import PermissionsViolation
|
||||
from utilities.forms import add_blank_choice
|
||||
from utilities.forms.fields import (
|
||||
CommentField, ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, NumericArrayField,
|
||||
SlugField, NumericRangeArrayField
|
||||
SlugField
|
||||
)
|
||||
from utilities.forms.rendering import FieldSet, InlineFields, ObjectAttribute, TabbedGroups
|
||||
from utilities.forms.widgets import DatePicker
|
||||
@ -633,13 +633,16 @@ class VLANGroupForm(NetBoxModelForm):
|
||||
}
|
||||
)
|
||||
slug = SlugField()
|
||||
vlan_id_ranges = NumericRangeArrayField(
|
||||
required=False
|
||||
allowed_vids = NumericArrayField(
|
||||
required=False,
|
||||
label=_('min/max VLAN IDs'),
|
||||
base_field=forms.IntegerField(),
|
||||
help_text=_('Comma-separated list of numeric VLAN IDs. A range may be specified using a hyphen.'),
|
||||
)
|
||||
|
||||
fieldsets = (
|
||||
FieldSet('name', 'slug', 'description', 'tags', name=_('VLAN Group')),
|
||||
FieldSet('vlan_id_ranges', name=_('Child VLANs')),
|
||||
FieldSet('allowed_vids', name=_('Child VLANs')),
|
||||
FieldSet(
|
||||
'scope_type', 'region', 'sitegroup', 'site', 'location', 'rack', 'clustergroup', 'cluster',
|
||||
name=_('Scope')
|
||||
@ -650,7 +653,7 @@ class VLANGroupForm(NetBoxModelForm):
|
||||
model = VLANGroup
|
||||
fields = [
|
||||
'name', 'slug', 'description', 'scope_type', 'region', 'sitegroup', 'site', 'location', 'rack',
|
||||
'clustergroup', 'cluster', 'vlan_id_ranges', 'tags',
|
||||
'clustergroup', 'cluster', 'allowed_vids', 'tags',
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
@ -251,7 +251,7 @@ class VLANType(NetBoxObjectType):
|
||||
class VLANGroupType(OrganizationalObjectType):
|
||||
|
||||
vlans: List[VLANType]
|
||||
vlan_id_ranges: List[str]
|
||||
allowed_vids: str
|
||||
|
||||
@strawberry_django.field
|
||||
def scope(self) -> Annotated[Union[
|
||||
|
@ -30,18 +30,13 @@ class Migration(migrations.Migration):
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='vlangroup',
|
||||
name='vlan_id_ranges',
|
||||
name='allowed_vids',
|
||||
field=django.contrib.postgres.fields.ArrayField(
|
||||
base_field=django.contrib.postgres.fields.ranges.BigIntegerRangeField(),
|
||||
blank=True, null=True, size=None,
|
||||
default=ipam.models.vlans.get_default_vlan_ids,
|
||||
base_field=models.PositiveSmallIntegerField(),
|
||||
default=ipam.models.vlans.get_default_allowed_vids,
|
||||
size=None,
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='vlangroup',
|
||||
name='_total_vlan_ids',
|
||||
field=models.PositiveBigIntegerField(default=4094),
|
||||
),
|
||||
migrations.RunPython(
|
||||
code=move_min_max,
|
||||
reverse_code=migrations.RunPython.noop
|
@ -1,9 +1,8 @@
|
||||
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
|
||||
from django.contrib.postgres.fields import ArrayField, BigIntegerRangeField
|
||||
from django.contrib.postgres.fields import ArrayField
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||
from django.db import models
|
||||
from django.db.backends.postgresql.psycopg_any import NumericRange
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
@ -21,8 +20,8 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
def get_default_vlan_ids():
|
||||
return [NumericRange(VLAN_VID_MIN, VLAN_VID_MAX)]
|
||||
def get_default_allowed_vids():
|
||||
return list(range(VLAN_VID_MIN, VLAN_VID_MAX + 1))
|
||||
|
||||
|
||||
class VLANGroup(OrganizationalModel):
|
||||
@ -52,16 +51,11 @@ class VLANGroup(OrganizationalModel):
|
||||
ct_field='scope_type',
|
||||
fk_field='scope_id'
|
||||
)
|
||||
vlan_id_ranges = ArrayField(
|
||||
BigIntegerRangeField(),
|
||||
allowed_vids = ArrayField(
|
||||
verbose_name=_('min/max VLAN IDs'),
|
||||
default=get_default_vlan_ids,
|
||||
help_text=_('Ranges of Minimum, maximum VLAN IDs'),
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
_total_vlan_ids = models.PositiveBigIntegerField(
|
||||
default=VLAN_VID_MAX - VLAN_VID_MIN + 1
|
||||
base_field=models.PositiveSmallIntegerField(),
|
||||
default=get_default_allowed_vids,
|
||||
help_text=_('Ranges of Minimum-maximum child VLAN VID'),
|
||||
)
|
||||
|
||||
objects = VLANGroupQuerySet.as_manager()
|
||||
|
@ -1,5 +1,5 @@
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db.models import Count, F, OuterRef, Q, Subquery, Value
|
||||
from django.db.models import Count, F, Func, OuterRef, Q, Subquery, Value
|
||||
from django.db.models.expressions import RawSQL
|
||||
from django.db.models.functions import Round
|
||||
|
||||
@ -63,7 +63,8 @@ class VLANGroupQuerySet(RestrictedQuerySet):
|
||||
|
||||
return self.annotate(
|
||||
vlan_count=count_related(VLAN, 'group'),
|
||||
utilization=Round(F('vlan_count') * 100 / F('_total_vlan_ids'), 2)
|
||||
total_allowed_vids=Func(F('allowed_vids'), function='CARDINALITY'),
|
||||
utilization=Round(F('vlan_count') * 100 / F('total_allowed_vids'), 2)
|
||||
)
|
||||
|
||||
|
||||
|
@ -7,7 +7,6 @@ from ..utils import parse_numeric_range
|
||||
|
||||
__all__ = (
|
||||
'NumericArrayField',
|
||||
'NumericRangeArrayField',
|
||||
)
|
||||
|
||||
|
||||
@ -26,33 +25,3 @@ class NumericArrayField(SimpleArrayField):
|
||||
if isinstance(value, str):
|
||||
value = ','.join([str(n) for n in parse_numeric_range(value)])
|
||||
return super().to_python(value)
|
||||
|
||||
|
||||
class NumericRangeArrayField(forms.CharField):
|
||||
"""
|
||||
A field which allows for array of numeric ranges:
|
||||
Example: 1-5,7-20,30-50
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
if not self.help_text:
|
||||
self.help_text = _(
|
||||
"Specify one or more numeric ranges separated by commas "
|
||||
"Example: <code>1-5,20-30</code>"
|
||||
)
|
||||
|
||||
def clean(self, value):
|
||||
if value and not self.to_python(value):
|
||||
raise forms.ValidationError(
|
||||
_("Invalid ranges ({value}). Must be range of number '100-200' and ranges must be in ascending order.").format(value=value)
|
||||
)
|
||||
return super().clean(value)
|
||||
|
||||
def prepare_value(self, value):
|
||||
if isinstance(value, str):
|
||||
return value
|
||||
return ranges_to_string(value)
|
||||
|
||||
def to_python(self, value):
|
||||
return string_to_range_array(value)
|
||||
|
Loading…
Reference in New Issue
Block a user