diff --git a/netbox/ipam/forms/model_forms.py b/netbox/ipam/forms/model_forms.py index d91a1caab..f06de2312 100644 --- a/netbox/ipam/forms/model_forms.py +++ b/netbox/ipam/forms/model_forms.py @@ -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, + SlugField, NumericRangeArrayField ) from utilities.forms.rendering import FieldSet, InlineFields, ObjectAttribute, TabbedGroups from utilities.forms.widgets import DatePicker @@ -637,7 +637,7 @@ class VLANGroupForm(NetBoxModelForm): # IntegerRangeField(), # delimiter="|" # ) - vlan_id_ranges = IntegerRangeField() + vlan_id_ranges = NumericRangeArrayField() fieldsets = ( FieldSet('name', 'slug', 'description', 'tags', name=_('VLAN Group')), diff --git a/netbox/ipam/migrations/0070_vlangroup_vlan_id_ranges.py b/netbox/ipam/migrations/0070_vlangroup_vlan_id_ranges.py new file mode 100644 index 000000000..880a868b9 --- /dev/null +++ b/netbox/ipam/migrations/0070_vlangroup_vlan_id_ranges.py @@ -0,0 +1,20 @@ +# Generated by Django 4.2.11 on 2024-06-20 19:28 + +import django.contrib.postgres.fields +import django.contrib.postgres.fields.ranges +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('ipam', '0069_gfk_indexes'), + ] + + operations = [ + migrations.AddField( + model_name='vlangroup', + name='vlan_id_ranges', + field=django.contrib.postgres.fields.ArrayField(base_field=django.contrib.postgres.fields.ranges.BigIntegerRangeField(), blank=True, null=True, size=None), + ), + ] diff --git a/netbox/ipam/models/vlans.py b/netbox/ipam/models/vlans.py index 83f8e0937..861b3fe3b 100644 --- a/netbox/ipam/models/vlans.py +++ b/netbox/ipam/models/vlans.py @@ -71,6 +71,7 @@ class VLANGroup(OrganizationalModel): blank=True, null=True ) + # vlan_id_ranges = BigIntegerRangeField(null=True, blank=True) objects = VLANGroupQuerySet.as_manager() diff --git a/netbox/utilities/forms/fields/expandable.py b/netbox/utilities/forms/fields/expandable.py index 959271a85..6330d9f5a 100644 --- a/netbox/utilities/forms/fields/expandable.py +++ b/netbox/utilities/forms/fields/expandable.py @@ -1,6 +1,7 @@ import re from django import forms +from django.db.backends.postgresql.psycopg_any import NumericRange from django.utils.translation import gettext_lazy as _ from utilities.forms.constants import * @@ -9,6 +10,7 @@ from utilities.forms.utils import expand_alphanumeric_pattern, expand_ipaddress_ __all__ = ( 'ExpandableIPAddressField', 'ExpandableNameField', + 'NumericRangeArrayField', ) @@ -53,3 +55,27 @@ class ExpandableIPAddressField(forms.CharField): elif ':' in value and re.search(IP6_EXPANSION_PATTERN, value): return list(expand_ipaddress_pattern(value, 6)) return [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: 1-5,20-30" + ) + + def to_python(self, value): + if not value: + return '' + ranges = split(value, ",") + numeric_ranges = [] + for range in ranges: + numeric_ranges.append(NumericRange(range[0], range[1])) + return [numeric_ranges]