diff --git a/netbox/circuits/forms/bulk_edit.py b/netbox/circuits/forms/bulk_edit.py index 5c416bff9..3ac311c56 100644 --- a/netbox/circuits/forms/bulk_edit.py +++ b/netbox/circuits/forms/bulk_edit.py @@ -8,6 +8,7 @@ from netbox.forms import NetBoxModelBulkEditForm from tenancy.models import Tenant from utilities.forms import add_blank_choice from utilities.forms.fields import ColorField, CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField +from utilities.forms.rendering import FieldSet from utilities.forms.widgets import DatePicker, NumberWithOptions __all__ = ( @@ -34,7 +35,7 @@ class ProviderBulkEditForm(NetBoxModelBulkEditForm): model = Provider fieldsets = ( - (None, ('asns', 'description')), + FieldSet('asns', 'description'), ) nullable_fields = ( 'asns', 'description', 'comments', @@ -56,7 +57,7 @@ class ProviderAccountBulkEditForm(NetBoxModelBulkEditForm): model = ProviderAccount fieldsets = ( - (None, ('provider', 'description')), + FieldSet('provider', 'description'), ) nullable_fields = ( 'description', 'comments', @@ -83,7 +84,7 @@ class ProviderNetworkBulkEditForm(NetBoxModelBulkEditForm): model = ProviderNetwork fieldsets = ( - (None, ('provider', 'service_id', 'description')), + FieldSet('provider', 'service_id', 'description'), ) nullable_fields = ( 'service_id', 'description', 'comments', @@ -103,7 +104,7 @@ class CircuitTypeBulkEditForm(NetBoxModelBulkEditForm): model = CircuitType fieldsets = ( - (None, ('color', 'description')), + FieldSet('color', 'description'), ) nullable_fields = ('color', 'description') @@ -164,9 +165,9 @@ class CircuitBulkEditForm(NetBoxModelBulkEditForm): model = Circuit fieldsets = ( - (_('Circuit'), ('provider', 'type', 'status', 'description')), - (_('Service Parameters'), ('provider_account', 'install_date', 'termination_date', 'commit_rate')), - (_('Tenancy'), ('tenant',)), + FieldSet('provider', 'type', 'status', 'description', name=_('Circuit')), + FieldSet('provider_account', 'install_date', 'termination_date', 'commit_rate', name=_('Service Parameters')), + FieldSet('tenant', name=_('Tenancy')), ) nullable_fields = ( 'tenant', 'commit_rate', 'description', 'comments', diff --git a/netbox/circuits/forms/filtersets.py b/netbox/circuits/forms/filtersets.py index 1e1abd068..01445ff6f 100644 --- a/netbox/circuits/forms/filtersets.py +++ b/netbox/circuits/forms/filtersets.py @@ -8,6 +8,7 @@ from ipam.models import ASN from netbox.forms import NetBoxModelFilterSetForm from tenancy.forms import TenancyFilterForm, ContactModelFilterForm from utilities.forms.fields import ColorField, DynamicModelMultipleChoiceField, TagFilterField +from utilities.forms.rendering import FieldSet from utilities.forms.widgets import DatePicker, NumberWithOptions __all__ = ( @@ -22,10 +23,10 @@ __all__ = ( class ProviderFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm): model = Provider fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Location'), ('region_id', 'site_group_id', 'site_id')), - (_('ASN'), ('asn',)), - (_('Contacts'), ('contact', 'contact_role', 'contact_group')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('region_id', 'site_group_id', 'site_id', name=_('Location')), + FieldSet('asn', name=_('ASN')), + FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')), ) region_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), @@ -61,8 +62,8 @@ class ProviderFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm): class ProviderAccountFilterForm(NetBoxModelFilterSetForm): model = ProviderAccount fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Attributes'), ('provider_id', 'account')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('provider_id', 'account', name=_('Attributes')), ) provider_id = DynamicModelMultipleChoiceField( queryset=Provider.objects.all(), @@ -79,8 +80,8 @@ class ProviderAccountFilterForm(NetBoxModelFilterSetForm): class ProviderNetworkFilterForm(NetBoxModelFilterSetForm): model = ProviderNetwork fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Attributes'), ('provider_id', 'service_id')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('provider_id', 'service_id', name=_('Attributes')), ) provider_id = DynamicModelMultipleChoiceField( queryset=Provider.objects.all(), @@ -98,8 +99,8 @@ class ProviderNetworkFilterForm(NetBoxModelFilterSetForm): class CircuitTypeFilterForm(NetBoxModelFilterSetForm): model = CircuitType fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Attributes'), ('color',)), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('color', name=_('Attributes')), ) tag = TagFilterField(model) @@ -112,12 +113,12 @@ class CircuitTypeFilterForm(NetBoxModelFilterSetForm): class CircuitFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFilterSetForm): model = Circuit fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Provider'), ('provider_id', 'provider_account_id', 'provider_network_id')), - (_('Attributes'), ('type_id', 'status', 'install_date', 'termination_date', 'commit_rate')), - (_('Location'), ('region_id', 'site_group_id', 'site_id')), - (_('Tenant'), ('tenant_group_id', 'tenant_id')), - (_('Contacts'), ('contact', 'contact_role', 'contact_group')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('provider_id', 'provider_account_id', 'provider_network_id', name=_('Provider')), + FieldSet('type_id', 'status', 'install_date', 'termination_date', 'commit_rate', name=_('Attributes')), + FieldSet('region_id', 'site_group_id', 'site_id', name=_('Location')), + FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), + FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')), ) selector_fields = ('filter_id', 'q', 'region_id', 'site_group_id', 'site_id', 'provider_id', 'provider_network_id') type_id = DynamicModelMultipleChoiceField( diff --git a/netbox/circuits/forms/model_forms.py b/netbox/circuits/forms/model_forms.py index d73da3a02..ee5e47ce7 100644 --- a/netbox/circuits/forms/model_forms.py +++ b/netbox/circuits/forms/model_forms.py @@ -7,7 +7,7 @@ from ipam.models import ASN from netbox.forms import NetBoxModelForm from tenancy.forms import TenancyForm from utilities.forms.fields import CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, SlugField -from utilities.forms.rendering import TabbedGroups +from utilities.forms.rendering import FieldSet, TabbedGroups from utilities.forms.widgets import DatePicker, NumberWithOptions __all__ = ( @@ -30,7 +30,7 @@ class ProviderForm(NetBoxModelForm): comments = CommentField() fieldsets = ( - (_('Provider'), ('name', 'slug', 'asns', 'description', 'tags')), + FieldSet('name', 'slug', 'asns', 'description', 'tags'), ) class Meta: @@ -62,7 +62,7 @@ class ProviderNetworkForm(NetBoxModelForm): comments = CommentField() fieldsets = ( - (_('Provider Network'), ('provider', 'name', 'service_id', 'description', 'tags')), + FieldSet('provider', 'name', 'service_id', 'description', 'tags'), ) class Meta: @@ -76,9 +76,7 @@ class CircuitTypeForm(NetBoxModelForm): slug = SlugField() fieldsets = ( - (_('Circuit Type'), ( - 'name', 'slug', 'color', 'description', 'tags', - )), + FieldSet('name', 'slug', 'color', 'description', 'tags'), ) class Meta: @@ -108,9 +106,9 @@ class CircuitForm(TenancyForm, NetBoxModelForm): comments = CommentField() fieldsets = ( - (_('Circuit'), ('provider', 'provider_account', 'cid', 'type', 'status', 'description', 'tags')), - (_('Service Parameters'), ('install_date', 'termination_date', 'commit_rate')), - (_('Tenancy'), ('tenant_group', 'tenant')), + FieldSet('provider', 'provider_account', 'cid', 'type', 'status', 'description', 'tags', name=_('Circuit')), + FieldSet('install_date', 'termination_date', 'commit_rate', name=_('Service Parameters')), + FieldSet('tenant_group', 'tenant', name=_('Tenancy')), ) class Meta: @@ -148,18 +146,15 @@ class CircuitTerminationForm(NetBoxModelForm): ) fieldsets = ( - (_('Circuit Termination'), ( - 'circuit', - 'term_side', - 'description', - 'tags', + FieldSet( + 'circuit', 'term_side', 'description', 'tags', TabbedGroups( - (_('Site'), 'site'), - (_('Provider Network'), 'provider_network'), + FieldSet('site', name=_('Site')), + FieldSet('provider_network', name=_('Provider Network')), ), - 'mark_connected', - )), - (_('Termination Details'), ('port_speed', 'upstream_speed', 'xconnect_id', 'pp_info')), + 'mark_connected', name=_('Circuit Termination') + ), + FieldSet('port_speed', 'upstream_speed', 'xconnect_id', 'pp_info', name=_('Termination Details')), ) class Meta: diff --git a/netbox/core/forms/bulk_edit.py b/netbox/core/forms/bulk_edit.py index bc2ef8fc9..c1f1fca4d 100644 --- a/netbox/core/forms/bulk_edit.py +++ b/netbox/core/forms/bulk_edit.py @@ -5,6 +5,7 @@ from core.models import * from netbox.forms import NetBoxModelBulkEditForm from netbox.utils import get_data_backend_choices from utilities.forms.fields import CommentField +from utilities.forms.rendering import FieldSet from utilities.forms.widgets import BulkEditNullBooleanSelect __all__ = ( @@ -41,7 +42,7 @@ class DataSourceBulkEditForm(NetBoxModelBulkEditForm): model = DataSource fieldsets = ( - (None, ('type', 'enabled', 'description', 'comments', 'parameters', 'ignore_rules')), + FieldSet('type', 'enabled', 'description', 'comments', 'parameters', 'ignore_rules'), ) nullable_fields = ( 'description', 'description', 'parameters', 'comments', 'parameters', 'ignore_rules', diff --git a/netbox/core/forms/filtersets.py b/netbox/core/forms/filtersets.py index bd74c0f14..60a3acc44 100644 --- a/netbox/core/forms/filtersets.py +++ b/netbox/core/forms/filtersets.py @@ -9,7 +9,8 @@ from netbox.forms.mixins import SavedFiltersMixin from netbox.utils import get_data_backend_choices from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES, FilterForm from utilities.forms.fields import ContentTypeChoiceField, DynamicModelMultipleChoiceField -from utilities.forms.widgets import APISelectMultiple, DateTimePicker +from utilities.forms.rendering import FieldSet +from utilities.forms.widgets import DateTimePicker __all__ = ( 'ConfigRevisionFilterForm', @@ -22,8 +23,8 @@ __all__ = ( class DataSourceFilterForm(NetBoxModelFilterSetForm): model = DataSource fieldsets = ( - (None, ('q', 'filter_id')), - (_('Data Source'), ('type', 'status')), + FieldSet('q', 'filter_id'), + FieldSet('type', 'status', name=_('Data Source')), ) type = forms.MultipleChoiceField( label=_('Type'), @@ -47,8 +48,8 @@ class DataSourceFilterForm(NetBoxModelFilterSetForm): class DataFileFilterForm(NetBoxModelFilterSetForm): model = DataFile fieldsets = ( - (None, ('q', 'filter_id')), - (_('File'), ('source_id',)), + FieldSet('q', 'filter_id'), + FieldSet('source_id', name=_('File')), ) source_id = DynamicModelMultipleChoiceField( queryset=DataSource.objects.all(), @@ -59,12 +60,12 @@ class DataFileFilterForm(NetBoxModelFilterSetForm): class JobFilterForm(SavedFiltersMixin, FilterForm): fieldsets = ( - (None, ('q', 'filter_id')), - (_('Attributes'), ('object_type', 'status')), - (_('Creation'), ( + FieldSet('q', 'filter_id'), + FieldSet('object_type', 'status', name=_('Attributes')), + FieldSet( 'created__before', 'created__after', 'scheduled__before', 'scheduled__after', 'started__before', - 'started__after', 'completed__before', 'completed__after', 'user', - )), + 'started__after', 'completed__before', 'completed__after', 'user', name=_('Creation') + ), ) object_type = ContentTypeChoiceField( label=_('Object Type'), @@ -125,5 +126,5 @@ class JobFilterForm(SavedFiltersMixin, FilterForm): class ConfigRevisionFilterForm(SavedFiltersMixin, FilterForm): fieldsets = ( - (None, ('q', 'filter_id')), + FieldSet('q', 'filter_id'), ) diff --git a/netbox/core/forms/model_forms.py b/netbox/core/forms/model_forms.py index e0c71fe48..cbca0737a 100644 --- a/netbox/core/forms/model_forms.py +++ b/netbox/core/forms/model_forms.py @@ -13,6 +13,7 @@ from netbox.registry import registry from netbox.utils import get_data_backend_choices from utilities.forms import get_field_value from utilities.forms.fields import CommentField +from utilities.forms.rendering import FieldSet from utilities.forms.widgets import HTMXSelect __all__ = ( @@ -49,11 +50,11 @@ class DataSourceForm(NetBoxModelForm): @property def fieldsets(self): fieldsets = [ - (_('Source'), ('name', 'type', 'source_url', 'enabled', 'description', 'tags', 'ignore_rules')), + FieldSet('name', 'type', 'source_url', 'enabled', 'description', 'tags', 'ignore_rules', name=_('Source')), ] if self.backend_fields: fieldsets.append( - (_('Backend Parameters'), self.backend_fields) + FieldSet(*self.backend_fields, name=_('Backend Parameters')) ) return fieldsets @@ -91,8 +92,8 @@ class ManagedFileForm(SyncedDataMixin, NetBoxModelForm): ) fieldsets = ( - (_('File Upload'), ('upload_file',)), - (_('Data Source'), ('data_source', 'data_file', 'auto_sync_enabled')), + FieldSet('upload_file', name=_('File Upload')), + FieldSet('data_source', 'data_file', 'auto_sync_enabled', name=_('Data Source')), ) class Meta: @@ -144,18 +145,24 @@ class ConfigRevisionForm(forms.ModelForm, metaclass=ConfigFormMetaclass): """ fieldsets = ( - (_('Rack Elevations'), ('RACK_ELEVATION_DEFAULT_UNIT_HEIGHT', 'RACK_ELEVATION_DEFAULT_UNIT_WIDTH')), - (_('Power'), ('POWERFEED_DEFAULT_VOLTAGE', 'POWERFEED_DEFAULT_AMPERAGE', 'POWERFEED_DEFAULT_MAX_UTILIZATION')), - (_('IPAM'), ('ENFORCE_GLOBAL_UNIQUE', 'PREFER_IPV4')), - (_('Security'), ('ALLOWED_URL_SCHEMES',)), - (_('Banners'), ('BANNER_LOGIN', 'BANNER_MAINTENANCE', 'BANNER_TOP', 'BANNER_BOTTOM')), - (_('Pagination'), ('PAGINATE_COUNT', 'MAX_PAGE_SIZE')), - (_('Validation'), ('CUSTOM_VALIDATORS', 'PROTECTION_RULES')), - (_('User Preferences'), ('DEFAULT_USER_PREFERENCES',)), - (_('Miscellaneous'), ( + FieldSet( + 'RACK_ELEVATION_DEFAULT_UNIT_HEIGHT', 'RACK_ELEVATION_DEFAULT_UNIT_WIDTH', name=_('Rack Elevations') + ), + FieldSet( + 'POWERFEED_DEFAULT_VOLTAGE', 'POWERFEED_DEFAULT_AMPERAGE', 'POWERFEED_DEFAULT_MAX_UTILIZATION', + name=_('Power') + ), + FieldSet('ENFORCE_GLOBAL_UNIQUE', 'PREFER_IPV4', name=_('IPAM')), + FieldSet('ALLOWED_URL_SCHEMES', name=_('Security')), + FieldSet('BANNER_LOGIN', 'BANNER_MAINTENANCE', 'BANNER_TOP', 'BANNER_BOTTOM', name=_('Banners')), + FieldSet('PAGINATE_COUNT', 'MAX_PAGE_SIZE', name=_('Pagination')), + FieldSet('CUSTOM_VALIDATORS', 'PROTECTION_RULES', name=_('Validation')), + FieldSet('DEFAULT_USER_PREFERENCES', name=_('User Preferences')), + FieldSet( 'MAINTENANCE_MODE', 'GRAPHQL_ENABLED', 'CHANGELOG_RETENTION', 'JOB_RETENTION', 'MAPS_URL', - )), - (_('Config Revision'), ('comment',)) + name=_('Miscellaneous') + ), + FieldSet('comment', name=_('Config Revision')) ) class Meta: diff --git a/netbox/dcim/forms/bulk_edit.py b/netbox/dcim/forms/bulk_edit.py index 79ecc8383..978a5d0a1 100644 --- a/netbox/dcim/forms/bulk_edit.py +++ b/netbox/dcim/forms/bulk_edit.py @@ -13,6 +13,7 @@ from netbox.forms import NetBoxModelBulkEditForm from tenancy.models import Tenant from utilities.forms import BulkEditForm, add_blank_choice, form_from_model from utilities.forms.fields import ColorField, CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField +from utilities.forms.rendering import FieldSet from utilities.forms.widgets import BulkEditNullBooleanSelect, NumberWithOptions from wireless.models import WirelessLAN, WirelessLANGroup from wireless.choices import WirelessRoleChoices @@ -75,7 +76,7 @@ class RegionBulkEditForm(NetBoxModelBulkEditForm): model = Region fieldsets = ( - (None, ('parent', 'description')), + FieldSet('parent', 'description'), ) nullable_fields = ('parent', 'description') @@ -94,7 +95,7 @@ class SiteGroupBulkEditForm(NetBoxModelBulkEditForm): model = SiteGroup fieldsets = ( - (None, ('parent', 'description')), + FieldSet('parent', 'description'), ) nullable_fields = ('parent', 'description') @@ -154,7 +155,7 @@ class SiteBulkEditForm(NetBoxModelBulkEditForm): model = Site fieldsets = ( - (None, ('status', 'region', 'group', 'tenant', 'asns', 'time_zone', 'description')), + FieldSet('status', 'region', 'group', 'tenant', 'asns', 'time_zone', 'description'), ) nullable_fields = ( 'region', 'group', 'tenant', 'asns', 'time_zone', 'description', 'comments', @@ -194,7 +195,7 @@ class LocationBulkEditForm(NetBoxModelBulkEditForm): model = Location fieldsets = ( - (None, ('site', 'parent', 'status', 'tenant', 'description')), + FieldSet('site', 'parent', 'status', 'tenant', 'description'), ) nullable_fields = ('parent', 'tenant', 'description') @@ -212,7 +213,7 @@ class RackRoleBulkEditForm(NetBoxModelBulkEditForm): model = RackRole fieldsets = ( - (None, ('color', 'description')), + FieldSet('color', 'description'), ) nullable_fields = ('color', 'description') @@ -341,12 +342,13 @@ class RackBulkEditForm(NetBoxModelBulkEditForm): model = Rack fieldsets = ( - (_('Rack'), ('status', 'role', 'tenant', 'serial', 'asset_tag', 'description')), - (_('Location'), ('region', 'site_group', 'site', 'location')), - (_('Hardware'), ( + FieldSet('status', 'role', 'tenant', 'serial', 'asset_tag', 'description', name=_('Rack')), + FieldSet('region', 'site_group', 'site', 'location', name=_('Location')), + FieldSet( 'type', 'width', 'u_height', 'desc_units', 'outer_width', 'outer_depth', 'outer_unit', 'mounting_depth', - )), - (_('Weight'), ('weight', 'max_weight', 'weight_unit')), + name=_('Hardware') + ), + FieldSet('weight', 'max_weight', 'weight_unit', name=_('Weight')), ) nullable_fields = ( 'location', 'tenant', 'role', 'serial', 'asset_tag', 'outer_width', 'outer_depth', 'outer_unit', 'weight', @@ -376,7 +378,7 @@ class RackReservationBulkEditForm(NetBoxModelBulkEditForm): model = RackReservation fieldsets = ( - (None, ('user', 'tenant', 'description')), + FieldSet('user', 'tenant', 'description'), ) nullable_fields = ('comments',) @@ -390,7 +392,7 @@ class ManufacturerBulkEditForm(NetBoxModelBulkEditForm): model = Manufacturer fieldsets = ( - (None, ('description',)), + FieldSet('description'), ) nullable_fields = ('description',) @@ -450,11 +452,11 @@ class DeviceTypeBulkEditForm(NetBoxModelBulkEditForm): model = DeviceType fieldsets = ( - (_('Device Type'), ( + FieldSet( 'manufacturer', 'default_platform', 'part_number', 'u_height', 'exclude_from_utilization', 'is_full_depth', - 'airflow', 'description', - )), - (_('Weight'), ('weight', 'weight_unit')), + 'airflow', 'description', name=_('Device Type') + ), + FieldSet('weight', 'weight_unit', name=_('Weight')), ) nullable_fields = ('part_number', 'airflow', 'weight', 'weight_unit', 'description', 'comments') @@ -489,8 +491,8 @@ class ModuleTypeBulkEditForm(NetBoxModelBulkEditForm): model = ModuleType fieldsets = ( - (_('Module Type'), ('manufacturer', 'part_number', 'description')), - (_('Weight'), ('weight', 'weight_unit')), + FieldSet('manufacturer', 'part_number', 'description', name=_('Module Type')), + FieldSet('weight', 'weight_unit', name=_('Weight')), ) nullable_fields = ('part_number', 'weight', 'weight_unit', 'description', 'comments') @@ -518,7 +520,7 @@ class DeviceRoleBulkEditForm(NetBoxModelBulkEditForm): model = DeviceRole fieldsets = ( - (None, ('color', 'vm_role', 'config_template', 'description')), + FieldSet('color', 'vm_role', 'config_template', 'description'), ) nullable_fields = ('color', 'config_template', 'description') @@ -542,7 +544,7 @@ class PlatformBulkEditForm(NetBoxModelBulkEditForm): model = Platform fieldsets = ( - (None, ('manufacturer', 'config_template', 'description')), + FieldSet('manufacturer', 'config_template', 'description'), ) nullable_fields = ('manufacturer', 'config_template', 'description') @@ -621,10 +623,10 @@ class DeviceBulkEditForm(NetBoxModelBulkEditForm): model = Device fieldsets = ( - (_('Device'), ('role', 'status', 'tenant', 'platform', 'description')), - (_('Location'), ('site', 'location')), - (_('Hardware'), ('manufacturer', 'device_type', 'airflow', 'serial')), - (_('Configuration'), ('config_template',)), + FieldSet('role', 'status', 'tenant', 'platform', 'description', name=_('Device')), + FieldSet('site', 'location', name=_('Location')), + FieldSet('manufacturer', 'device_type', 'airflow', 'serial', name=_('Hardware')), + FieldSet('config_template', name=_('Configuration')), ) nullable_fields = ( 'location', 'tenant', 'platform', 'serial', 'airflow', 'description', 'comments', @@ -668,7 +670,7 @@ class ModuleBulkEditForm(NetBoxModelBulkEditForm): model = Module fieldsets = ( - (None, ('manufacturer', 'module_type', 'status', 'serial', 'description')), + FieldSet('manufacturer', 'module_type', 'status', 'serial', 'description'), ) nullable_fields = ('serial', 'description', 'comments') @@ -720,8 +722,8 @@ class CableBulkEditForm(NetBoxModelBulkEditForm): model = Cable fieldsets = ( - (None, ('type', 'status', 'tenant', 'label', 'description')), - (_('Attributes'), ('color', 'length', 'length_unit')), + FieldSet('type', 'status', 'tenant', 'label', 'description'), + FieldSet('color', 'length', 'length_unit', name=_('Attributes')), ) nullable_fields = ( 'type', 'status', 'tenant', 'label', 'color', 'length', 'description', 'comments', @@ -743,7 +745,7 @@ class VirtualChassisBulkEditForm(NetBoxModelBulkEditForm): model = VirtualChassis fieldsets = ( - (None, ('domain', 'description')), + FieldSet('domain', 'description'), ) nullable_fields = ('domain', 'description', 'comments') @@ -791,7 +793,7 @@ class PowerPanelBulkEditForm(NetBoxModelBulkEditForm): model = PowerPanel fieldsets = ( - (None, ('region', 'site_group', 'site', 'location', 'description')), + FieldSet('region', 'site_group', 'site', 'location', 'description'), ) nullable_fields = ('location', 'description', 'comments') @@ -861,8 +863,8 @@ class PowerFeedBulkEditForm(NetBoxModelBulkEditForm): model = PowerFeed fieldsets = ( - (None, ('power_panel', 'rack', 'status', 'type', 'mark_connected', 'description', 'tenant')), - (_('Power'), ('supply', 'phase', 'voltage', 'amperage', 'max_utilization')) + FieldSet('power_panel', 'rack', 'status', 'type', 'mark_connected', 'description', 'tenant'), + FieldSet('supply', 'phase', 'voltage', 'amperage', 'max_utilization', name=_('Power')) ) nullable_fields = ('location', 'tenant', 'description', 'comments') @@ -1210,7 +1212,7 @@ class ConsolePortBulkEditForm( model = ConsolePort fieldsets = ( - (None, ('module', 'type', 'label', 'speed', 'description', 'mark_connected')), + FieldSet('module', 'type', 'label', 'speed', 'description', 'mark_connected'), ) nullable_fields = ('module', 'label', 'description') @@ -1227,7 +1229,7 @@ class ConsoleServerPortBulkEditForm( model = ConsoleServerPort fieldsets = ( - (None, ('module', 'type', 'label', 'speed', 'description', 'mark_connected')), + FieldSet('module', 'type', 'label', 'speed', 'description', 'mark_connected'), ) nullable_fields = ('module', 'label', 'description') @@ -1244,8 +1246,8 @@ class PowerPortBulkEditForm( model = PowerPort fieldsets = ( - (None, ('module', 'type', 'label', 'description', 'mark_connected')), - (_('Power'), ('maximum_draw', 'allocated_draw')), + FieldSet('module', 'type', 'label', 'description', 'mark_connected'), + FieldSet('maximum_draw', 'allocated_draw', name=_('Power')), ) nullable_fields = ('module', 'label', 'description', 'maximum_draw', 'allocated_draw') @@ -1262,8 +1264,8 @@ class PowerOutletBulkEditForm( model = PowerOutlet fieldsets = ( - (None, ('module', 'type', 'label', 'description', 'mark_connected')), - (_('Power'), ('feed_leg', 'power_port')), + FieldSet('module', 'type', 'label', 'description', 'mark_connected'), + FieldSet('feed_leg', 'power_port', name=_('Power')), ) nullable_fields = ('module', 'label', 'type', 'feed_leg', 'power_port', 'description') @@ -1395,20 +1397,21 @@ class InterfaceBulkEditForm( model = Interface fieldsets = ( - (None, ('module', 'type', 'label', 'speed', 'duplex', 'description')), - (_('Addressing'), ('vrf', 'mac_address', 'wwn')), - (_('Operation'), ('vdcs', 'mtu', 'tx_power', 'enabled', 'mgmt_only', 'mark_connected')), - (_('PoE'), ('poe_mode', 'poe_type')), - (_('Related Interfaces'), ('parent', 'bridge', 'lag')), - (_('802.1Q Switching'), ('mode', 'vlan_group', 'untagged_vlan', 'tagged_vlans')), - (_('Wireless'), ( + FieldSet('module', 'type', 'label', 'speed', 'duplex', 'description'), + FieldSet('vrf', 'mac_address', 'wwn', name=_('Addressing')), + FieldSet('vdcs', 'mtu', 'tx_power', 'enabled', 'mgmt_only', 'mark_connected', name=_('Operation')), + FieldSet('poe_mode', 'poe_type', name=_('PoE')), + FieldSet('parent', 'bridge', 'lag', name=_('Related Interfaces')), + FieldSet('mode', 'vlan_group', 'untagged_vlan', 'tagged_vlans', name=_('802.1Q Switching')), + FieldSet( 'rf_role', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width', 'wireless_lan_group', 'wireless_lans', - )), + name=_('Wireless') + ), ) nullable_fields = ( - 'module', 'label', 'parent', 'bridge', 'lag', 'speed', 'duplex', 'mac_address', 'wwn', 'vdcs', 'mtu', 'description', - 'poe_mode', 'poe_type', 'mode', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width', 'tx_power', 'untagged_vlan', - 'tagged_vlans', 'vrf', 'wireless_lans' + 'module', 'label', 'parent', 'bridge', 'lag', 'speed', 'duplex', 'mac_address', 'wwn', 'vdcs', 'mtu', + 'description', 'poe_mode', 'poe_type', 'mode', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width', + 'tx_power', 'untagged_vlan', 'tagged_vlans', 'vrf', 'wireless_lans' ) def __init__(self, *args, **kwargs): @@ -1488,7 +1491,7 @@ class FrontPortBulkEditForm( model = FrontPort fieldsets = ( - (None, ('module', 'type', 'label', 'color', 'description', 'mark_connected')), + FieldSet('module', 'type', 'label', 'color', 'description', 'mark_connected'), ) nullable_fields = ('module', 'label', 'description', 'color') @@ -1505,7 +1508,7 @@ class RearPortBulkEditForm( model = RearPort fieldsets = ( - (None, ('module', 'type', 'label', 'color', 'description', 'mark_connected')), + FieldSet('module', 'type', 'label', 'color', 'description', 'mark_connected'), ) nullable_fields = ('module', 'label', 'description', 'color') @@ -1516,7 +1519,7 @@ class ModuleBayBulkEditForm( ): model = ModuleBay fieldsets = ( - (None, ('label', 'position', 'description')), + FieldSet('label', 'position', 'description'), ) nullable_fields = ('label', 'position', 'description') @@ -1527,7 +1530,7 @@ class DeviceBayBulkEditForm( ): model = DeviceBay fieldsets = ( - (None, ('label', 'description')), + FieldSet('label', 'description'), ) nullable_fields = ('label', 'description') @@ -1554,7 +1557,7 @@ class InventoryItemBulkEditForm( model = InventoryItem fieldsets = ( - (None, ('device', 'label', 'role', 'manufacturer', 'part_id', 'description')), + FieldSet('device', 'label', 'role', 'manufacturer', 'part_id', 'description'), ) nullable_fields = ('label', 'role', 'manufacturer', 'part_id', 'description') @@ -1576,7 +1579,7 @@ class InventoryItemRoleBulkEditForm(NetBoxModelBulkEditForm): model = InventoryItemRole fieldsets = ( - (None, ('color', 'description')), + FieldSet('color', 'description'), ) nullable_fields = ('color', 'description') @@ -1599,6 +1602,6 @@ class VirtualDeviceContextBulkEditForm(NetBoxModelBulkEditForm): ) model = VirtualDeviceContext fieldsets = ( - (None, ('device', 'status', 'tenant')), + FieldSet('device', 'status', 'tenant'), ) nullable_fields = ('device', 'tenant', ) diff --git a/netbox/dcim/forms/filtersets.py b/netbox/dcim/forms/filtersets.py index e35055851..4e8e3491c 100644 --- a/netbox/dcim/forms/filtersets.py +++ b/netbox/dcim/forms/filtersets.py @@ -12,7 +12,8 @@ from netbox.forms import NetBoxModelFilterSetForm from tenancy.forms import ContactModelFilterForm, TenancyFilterForm from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES, FilterForm, add_blank_choice from utilities.forms.fields import ColorField, DynamicModelMultipleChoiceField, TagFilterField -from utilities.forms.widgets import APISelectMultiple, NumberWithOptions +from utilities.forms.rendering import FieldSet +from utilities.forms.widgets import NumberWithOptions from vpn.models import L2VPN from wireless.choices import * @@ -132,8 +133,8 @@ class DeviceComponentFilterForm(NetBoxModelFilterSetForm): class RegionFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm): model = Region fieldsets = ( - (None, ('q', 'filter_id', 'tag', 'parent_id')), - (_('Contacts'), ('contact', 'contact_role', 'contact_group')) + FieldSet('q', 'filter_id', 'tag', 'parent_id'), + FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')) ) parent_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), @@ -146,8 +147,8 @@ class RegionFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm): class SiteGroupFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm): model = SiteGroup fieldsets = ( - (None, ('q', 'filter_id', 'tag', 'parent_id')), - (_('Contacts'), ('contact', 'contact_role', 'contact_group')) + FieldSet('q', 'filter_id', 'tag', 'parent_id'), + FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')) ) parent_id = DynamicModelMultipleChoiceField( queryset=SiteGroup.objects.all(), @@ -160,10 +161,10 @@ class SiteGroupFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm): class SiteFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFilterSetForm): model = Site fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Attributes'), ('status', 'region_id', 'group_id', 'asn_id')), - (_('Tenant'), ('tenant_group_id', 'tenant_id')), - (_('Contacts'), ('contact', 'contact_role', 'contact_group')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('status', 'region_id', 'group_id', 'asn_id', name=_('Attributes')), + FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), + FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')), ) selector_fields = ('filter_id', 'q', 'region_id', 'group_id') status = forms.MultipleChoiceField( @@ -192,10 +193,10 @@ class SiteFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFilte class LocationFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFilterSetForm): model = Location fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Attributes'), ('region_id', 'site_group_id', 'site_id', 'parent_id', 'status')), - (_('Tenant'), ('tenant_group_id', 'tenant_id')), - (_('Contacts'), ('contact', 'contact_role', 'contact_group')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('region_id', 'site_group_id', 'site_id', 'parent_id', 'status', name=_('Attributes')), + FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), + FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')), ) region_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), @@ -241,13 +242,13 @@ class RackRoleFilterForm(NetBoxModelFilterSetForm): class RackFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFilterSetForm): model = Rack fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Location'), ('region_id', 'site_group_id', 'site_id', 'location_id')), - (_('Function'), ('status', 'role_id')), - (_('Hardware'), ('type', 'width', 'serial', 'asset_tag')), - (_('Tenant'), ('tenant_group_id', 'tenant_id')), - (_('Contacts'), ('contact', 'contact_role', 'contact_group')), - (_('Weight'), ('weight', 'max_weight', 'weight_unit')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', name=_('Location')), + FieldSet('status', 'role_id', name=_('Function')), + FieldSet('type', 'width', 'serial', 'asset_tag', name=_('Hardware')), + FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), + FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')), + FieldSet('weight', 'max_weight', 'weight_unit', name=_('Weight')), ) selector_fields = ('filter_id', 'q', 'region_id', 'site_group_id', 'site_id', 'location_id') region_id = DynamicModelMultipleChoiceField( @@ -326,13 +327,13 @@ class RackFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFilte class RackElevationFilterForm(RackFilterForm): fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Location'), ('region_id', 'site_group_id', 'site_id', 'location_id', 'id')), - (_('Function'), ('status', 'role_id')), - (_('Hardware'), ('type', 'width', 'serial', 'asset_tag')), - (_('Tenant'), ('tenant_group_id', 'tenant_id')), - (_('Contacts'), ('contact', 'contact_role', 'contact_group')), - (_('Weight'), ('weight', 'max_weight', 'weight_unit')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'id', name=_('Location')), + FieldSet('status', 'role_id', name=_('Function')), + FieldSet('type', 'width', 'serial', 'asset_tag', name=_('Hardware')), + FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), + FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')), + FieldSet('weight', 'max_weight', 'weight_unit', name=_('Weight')), ) id = DynamicModelMultipleChoiceField( queryset=Rack.objects.all(), @@ -348,10 +349,10 @@ class RackElevationFilterForm(RackFilterForm): class RackReservationFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = RackReservation fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('User'), ('user_id',)), - (_('Rack'), ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id')), - (_('Tenant'), ('tenant_group_id', 'tenant_id')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('user_id', name=_('User')), + FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Rack')), + FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), ) region_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), @@ -401,8 +402,8 @@ class RackReservationFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): class ManufacturerFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm): model = Manufacturer fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Contacts'), ('contact', 'contact_role', 'contact_group')) + FieldSet('q', 'filter_id', 'tag'), + FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')) ) tag = TagFilterField(model) @@ -410,14 +411,16 @@ class ManufacturerFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm): class DeviceTypeFilterForm(NetBoxModelFilterSetForm): model = DeviceType fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Hardware'), ('manufacturer_id', 'default_platform_id', 'part_number', 'subdevice_role', 'airflow')), - (_('Images'), ('has_front_image', 'has_rear_image')), - (_('Components'), ( + FieldSet('q', 'filter_id', 'tag'), + FieldSet( + 'manufacturer_id', 'default_platform_id', 'part_number', 'subdevice_role', 'airflow', name=_('Hardware') + ), + FieldSet('has_front_image', 'has_rear_image', name=_('Images')), + FieldSet( 'console_ports', 'console_server_ports', 'power_ports', 'power_outlets', 'interfaces', - 'pass_through_ports', 'device_bays', 'module_bays', 'inventory_items', - )), - (_('Weight'), ('weight', 'weight_unit')), + 'pass_through_ports', 'device_bays', 'module_bays', 'inventory_items', name=_('Components') + ), + FieldSet('weight', 'weight_unit', name=_('Weight')), ) selector_fields = ('filter_id', 'q', 'manufacturer_id') manufacturer_id = DynamicModelMultipleChoiceField( @@ -536,13 +539,13 @@ class DeviceTypeFilterForm(NetBoxModelFilterSetForm): class ModuleTypeFilterForm(NetBoxModelFilterSetForm): model = ModuleType fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Hardware'), ('manufacturer_id', 'part_number')), - (_('Components'), ( + FieldSet('q', 'filter_id', 'tag'), + FieldSet('manufacturer_id', 'part_number', name=_('Hardware')), + FieldSet( 'console_ports', 'console_server_ports', 'power_ports', 'power_outlets', 'interfaces', - 'pass_through_ports', - )), - (_('Weight'), ('weight', 'weight_unit')), + 'pass_through_ports', name=_('Components') + ), + FieldSet('weight', 'weight_unit', name=_('Weight')), ) selector_fields = ('filter_id', 'q', 'manufacturer_id') manufacturer_id = DynamicModelMultipleChoiceField( @@ -642,18 +645,20 @@ class DeviceFilterForm( ): model = Device fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Location'), ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id')), - (_('Operation'), ('status', 'role_id', 'airflow', 'serial', 'asset_tag', 'mac_address')), - (_('Hardware'), ('manufacturer_id', 'device_type_id', 'platform_id')), - (_('Tenant'), ('tenant_group_id', 'tenant_id')), - (_('Contacts'), ('contact', 'contact_role', 'contact_group')), - (_('Components'), ( + FieldSet('q', 'filter_id', 'tag'), + FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')), + FieldSet('status', 'role_id', 'airflow', 'serial', 'asset_tag', 'mac_address', name=_('Operation')), + FieldSet('manufacturer_id', 'device_type_id', 'platform_id', name=_('Hardware')), + FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), + FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')), + FieldSet( 'console_ports', 'console_server_ports', 'power_ports', 'power_outlets', 'interfaces', 'pass_through_ports', - )), - (_('Miscellaneous'), ( + name=_('Components') + ), + FieldSet( 'has_primary_ip', 'has_oob_ip', 'virtual_chassis_member', 'config_template_id', 'local_context_data', - )) + name=_('Miscellaneous') + ) ) selector_fields = ('filter_id', 'q', 'region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id') region_id = DynamicModelMultipleChoiceField( @@ -817,9 +822,9 @@ class VirtualDeviceContextFilterForm( ): model = VirtualDeviceContext fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Attributes'), ('device', 'status', 'has_primary_ip')), - (_('Tenant'), ('tenant_group_id', 'tenant_id')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('device', 'status', 'has_primary_ip', name=_('Attributes')), + FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), ) device = DynamicModelMultipleChoiceField( queryset=Device.objects.all(), @@ -844,8 +849,8 @@ class VirtualDeviceContextFilterForm( class ModuleFilterForm(LocalConfigContextFilterForm, TenancyFilterForm, NetBoxModelFilterSetForm): model = Module fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Hardware'), ('manufacturer_id', 'module_type_id', 'status', 'serial', 'asset_tag')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('manufacturer_id', 'module_type_id', 'status', 'serial', 'asset_tag', name=_('Hardware')), ) manufacturer_id = DynamicModelMultipleChoiceField( queryset=Manufacturer.objects.all(), @@ -879,9 +884,9 @@ class ModuleFilterForm(LocalConfigContextFilterForm, TenancyFilterForm, NetBoxMo class VirtualChassisFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = VirtualChassis fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Location'), ('region_id', 'site_group_id', 'site_id')), - (_('Tenant'), ('tenant_group_id', 'tenant_id')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('region_id', 'site_group_id', 'site_id', name=_('Location')), + FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), ) region_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), @@ -908,10 +913,10 @@ class VirtualChassisFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): class CableFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = Cable fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Location'), ('site_id', 'location_id', 'rack_id', 'device_id')), - (_('Attributes'), ('type', 'status', 'color', 'length', 'length_unit', 'unterminated')), - (_('Tenant'), ('tenant_group_id', 'tenant_id')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('site_id', 'location_id', 'rack_id', 'device_id', name=_('Location')), + FieldSet('type', 'status', 'color', 'length', 'length_unit', 'unterminated', name=_('Attributes')), + FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), ) region_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), @@ -992,9 +997,9 @@ class CableFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): class PowerPanelFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm): model = PowerPanel fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Location'), ('region_id', 'site_group_id', 'site_id', 'location_id')), - (_('Contacts'), ('contact', 'contact_role', 'contact_group')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', name=_('Location')), + FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')), ) selector_fields = ('filter_id', 'q', 'site_id', 'location_id') region_id = DynamicModelMultipleChoiceField( @@ -1031,10 +1036,10 @@ class PowerPanelFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm): class PowerFeedFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = PowerFeed fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Location'), ('region_id', 'site_group_id', 'site_id', 'power_panel_id', 'rack_id')), - (_('Tenant'), ('tenant_group_id', 'tenant_id')), - (_('Attributes'), ('status', 'type', 'supply', 'phase', 'voltage', 'amperage', 'max_utilization')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('region_id', 'site_group_id', 'site_id', 'power_panel_id', 'rack_id', name=_('Location')), + FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), + FieldSet('status', 'type', 'supply', 'phase', 'voltage', 'amperage', 'max_utilization', name=_('Attributes')), ) region_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), @@ -1141,11 +1146,11 @@ class PathEndpointFilterForm(CabledFilterForm): class ConsolePortFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm): model = ConsolePort fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Attributes'), ('name', 'label', 'type', 'speed')), - (_('Location'), ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id')), - (_('Device'), ('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id')), - (_('Connection'), ('cabled', 'connected', 'occupied')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('name', 'label', 'type', 'speed', name=_('Attributes')), + FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')), + FieldSet('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id', name=_('Device')), + FieldSet('cabled', 'connected', 'occupied', name=_('Connection')), ) type = forms.MultipleChoiceField( label=_('Type'), @@ -1163,11 +1168,11 @@ class ConsolePortFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm): class ConsoleServerPortFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm): model = ConsoleServerPort fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Attributes'), ('name', 'label', 'type', 'speed')), - (_('Location'), ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id')), - (_('Device'), ('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id')), - (_('Connection'), ('cabled', 'connected', 'occupied')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('name', 'label', 'type', 'speed', name=_('Attributes')), + FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')), + FieldSet('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id', name=_('Device')), + FieldSet('cabled', 'connected', 'occupied', name=_('Connection')), ) type = forms.MultipleChoiceField( label=_('Type'), @@ -1185,11 +1190,11 @@ class ConsoleServerPortFilterForm(PathEndpointFilterForm, DeviceComponentFilterF class PowerPortFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm): model = PowerPort fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Attributes'), ('name', 'label', 'type')), - (_('Location'), ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id')), - (_('Device'), ('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id')), - (_('Connection'), ('cabled', 'connected', 'occupied')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('name', 'label', 'type', name=_('Attributes')), + FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')), + FieldSet('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id', name=_('Device')), + FieldSet('cabled', 'connected', 'occupied', name=_('Connection')), ) type = forms.MultipleChoiceField( label=_('Type'), @@ -1202,11 +1207,11 @@ class PowerPortFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm): class PowerOutletFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm): model = PowerOutlet fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Attributes'), ('name', 'label', 'type')), - (_('Location'), ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id')), - (_('Device'), ('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id')), - (_('Connection'), ('cabled', 'connected', 'occupied')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('name', 'label', 'type', name=_('Attributes')), + FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')), + FieldSet('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id', name=_('Device')), + FieldSet('cabled', 'connected', 'occupied', name=_('Connection')), ) type = forms.MultipleChoiceField( label=_('Type'), @@ -1219,14 +1224,14 @@ class PowerOutletFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm): class InterfaceFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm): model = Interface fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Attributes'), ('name', 'label', 'kind', 'type', 'speed', 'duplex', 'enabled', 'mgmt_only')), - (_('Addressing'), ('vrf_id', 'l2vpn_id', 'mac_address', 'wwn')), - (_('PoE'), ('poe_mode', 'poe_type')), - (_('Wireless'), ('rf_role', 'rf_channel', 'rf_channel_width', 'tx_power')), - (_('Location'), ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id')), - (_('Device'), ('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id', 'vdc_id')), - (_('Connection'), ('cabled', 'connected', 'occupied')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('name', 'label', 'kind', 'type', 'speed', 'duplex', 'enabled', 'mgmt_only', name=_('Attributes')), + FieldSet('vrf_id', 'l2vpn_id', 'mac_address', 'wwn', name=_('Addressing')), + FieldSet('poe_mode', 'poe_type', name=_('PoE')), + FieldSet('rf_role', 'rf_channel', 'rf_channel_width', 'tx_power', name=_('Wireless')), + FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')), + FieldSet('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id', 'vdc_id', name=_('Device')), + FieldSet('cabled', 'connected', 'occupied', name=_('Connection')), ) selector_fields = ('filter_id', 'q', 'device_id') vdc_id = DynamicModelMultipleChoiceField( @@ -1330,11 +1335,11 @@ class InterfaceFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm): class FrontPortFilterForm(CabledFilterForm, DeviceComponentFilterForm): fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Attributes'), ('name', 'label', 'type', 'color')), - (_('Location'), ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id')), - (_('Device'), ('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id')), - (_('Cable'), ('cabled', 'occupied')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('name', 'label', 'type', 'color', name=_('Attributes')), + FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')), + FieldSet('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id', name=_('Device')), + FieldSet('cabled', 'occupied', name=_('Cable')), ) model = FrontPort type = forms.MultipleChoiceField( @@ -1352,11 +1357,11 @@ class FrontPortFilterForm(CabledFilterForm, DeviceComponentFilterForm): class RearPortFilterForm(CabledFilterForm, DeviceComponentFilterForm): model = RearPort fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Attributes'), ('name', 'label', 'type', 'color')), - (_('Location'), ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id')), - (_('Device'), ('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id')), - (_('Cable'), ('cabled', 'occupied')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('name', 'label', 'type', 'color', name=_('Attributes')), + FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')), + FieldSet('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id', name=_('Device')), + FieldSet('cabled', 'occupied', name=_('Cable')), ) type = forms.MultipleChoiceField( label=_('Type'), @@ -1373,10 +1378,10 @@ class RearPortFilterForm(CabledFilterForm, DeviceComponentFilterForm): class ModuleBayFilterForm(DeviceComponentFilterForm): model = ModuleBay fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Attributes'), ('name', 'label', 'position')), - (_('Location'), ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id')), - (_('Device'), ('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('name', 'label', 'position', name=_('Attributes')), + FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')), + FieldSet('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id', name=_('Device')), ) tag = TagFilterField(model) position = forms.CharField( @@ -1388,10 +1393,10 @@ class ModuleBayFilterForm(DeviceComponentFilterForm): class DeviceBayFilterForm(DeviceComponentFilterForm): model = DeviceBay fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Attributes'), ('name', 'label')), - (_('Location'), ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id')), - (_('Device'), ('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('name', 'label', name=_('Attributes')), + FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')), + FieldSet('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id', name=_('Device')), ) tag = TagFilterField(model) @@ -1399,10 +1404,13 @@ class DeviceBayFilterForm(DeviceComponentFilterForm): class InventoryItemFilterForm(DeviceComponentFilterForm): model = InventoryItem fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Attributes'), ('name', 'label', 'role_id', 'manufacturer_id', 'serial', 'asset_tag', 'discovered')), - (_('Location'), ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id')), - (_('Device'), ('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet( + 'name', 'label', 'role_id', 'manufacturer_id', 'serial', 'asset_tag', 'discovered', + name=_('Attributes') + ), + FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')), + FieldSet('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id', name=_('Device')), ) role_id = DynamicModelMultipleChoiceField( queryset=InventoryItemRole.objects.all(), diff --git a/netbox/dcim/forms/model_forms.py b/netbox/dcim/forms/model_forms.py index e0c25dbba..3559aabc6 100644 --- a/netbox/dcim/forms/model_forms.py +++ b/netbox/dcim/forms/model_forms.py @@ -16,7 +16,7 @@ from utilities.forms.fields import ( CommentField, ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, JSONField, NumericArrayField, SlugField, ) -from utilities.forms.rendering import InlineFields, TabbedGroups +from utilities.forms.rendering import FieldSet, InlineFields, TabbedGroups from utilities.forms.widgets import APISelect, ClearableFileInput, HTMXSelect, NumberWithOptions, SelectWithPK from virtualization.models import Cluster from wireless.models import WirelessLAN, WirelessLANGroup @@ -78,9 +78,7 @@ class RegionForm(NetBoxModelForm): slug = SlugField() fieldsets = ( - (_('Region'), ( - 'parent', 'name', 'slug', 'description', 'tags', - )), + FieldSet('parent', 'name', 'slug', 'description', 'tags'), ) class Meta: @@ -99,9 +97,7 @@ class SiteGroupForm(NetBoxModelForm): slug = SlugField() fieldsets = ( - (_('Site Group'), ( - 'parent', 'name', 'slug', 'description', 'tags', - )), + FieldSet('parent', 'name', 'slug', 'description', 'tags'), ) class Meta: @@ -136,11 +132,12 @@ class SiteForm(TenancyForm, NetBoxModelForm): comments = CommentField() fieldsets = ( - (_('Site'), ( + FieldSet( 'name', 'slug', 'status', 'region', 'group', 'facility', 'asns', 'time_zone', 'description', 'tags', - )), - (_('Tenancy'), ('tenant_group', 'tenant')), - (_('Contact Info'), ('physical_address', 'shipping_address', 'latitude', 'longitude')), + name=_('Site') + ), + FieldSet('tenant_group', 'tenant', name=_('Tenancy')), + FieldSet('physical_address', 'shipping_address', 'latitude', 'longitude', name=_('Contact Info')), ) class Meta: @@ -180,8 +177,8 @@ class LocationForm(TenancyForm, NetBoxModelForm): slug = SlugField() fieldsets = ( - (_('Location'), ('site', 'parent', 'name', 'slug', 'status', 'facility', 'description', 'tags')), - (_('Tenancy'), ('tenant_group', 'tenant')), + FieldSet('site', 'parent', 'name', 'slug', 'status', 'facility', 'description', 'tags', name=_('Location')), + FieldSet('tenant_group', 'tenant', name=_('Tenancy')), ) class Meta: @@ -195,9 +192,7 @@ class RackRoleForm(NetBoxModelForm): slug = SlugField() fieldsets = ( - (_('Rack Role'), ( - 'name', 'slug', 'color', 'description', 'tags', - )), + FieldSet('name', 'slug', 'color', 'description', 'tags', name=_('Rack Role')), ) class Meta: @@ -229,19 +224,15 @@ class RackForm(TenancyForm, NetBoxModelForm): comments = CommentField() fieldsets = ( - (_('Rack'), ('site', 'location', 'name', 'status', 'role', 'description', 'tags')), - (_('Inventory Control'), ('facility_id', 'serial', 'asset_tag')), - (_('Tenancy'), ('tenant_group', 'tenant')), - (_('Dimensions'), ( - 'type', - 'width', - 'starting_unit', - 'u_height', + FieldSet('site', 'location', 'name', 'status', 'role', 'description', 'tags', name=_('Rack')), + FieldSet('facility_id', 'serial', 'asset_tag', name=_('Inventory Control')), + FieldSet('tenant_group', 'tenant', name=_('Tenancy')), + FieldSet( + 'type', 'width', 'starting_unit', 'u_height', InlineFields('outer_width', 'outer_depth', 'outer_unit', label=_('Outer Dimensions')), InlineFields('weight', 'max_weight', 'weight_unit', label=_('Weight')), - 'mounting_depth', - 'desc_units', - )), + 'mounting_depth', 'desc_units', name=_('Dimensions') + ), ) class Meta: @@ -273,8 +264,8 @@ class RackReservationForm(TenancyForm, NetBoxModelForm): comments = CommentField() fieldsets = ( - (_('Reservation'), ('rack', 'units', 'user', 'description', 'tags')), - (_('Tenancy'), ('tenant_group', 'tenant')), + FieldSet('rack', 'units', 'user', 'description', 'tags', name=_('Reservation')), + FieldSet('tenant_group', 'tenant', name=_('Tenancy')), ) class Meta: @@ -288,9 +279,7 @@ class ManufacturerForm(NetBoxModelForm): slug = SlugField() fieldsets = ( - (_('Manufacturer'), ( - 'name', 'slug', 'description', 'tags', - )), + FieldSet('name', 'slug', 'description', 'tags', name=_('Manufacturer')), ) class Meta: @@ -321,12 +310,12 @@ class DeviceTypeForm(NetBoxModelForm): comments = CommentField() fieldsets = ( - (_('Device Type'), ('manufacturer', 'model', 'slug', 'default_platform', 'description', 'tags')), - (_('Chassis'), ( + FieldSet('manufacturer', 'model', 'slug', 'default_platform', 'description', 'tags', name=_('Device Type')), + FieldSet( 'u_height', 'exclude_from_utilization', 'is_full_depth', 'part_number', 'subdevice_role', 'airflow', - 'weight', 'weight_unit', - )), - (_('Images'), ('front_image', 'rear_image')), + 'weight', 'weight_unit', name=_('Chassis') + ), + FieldSet('front_image', 'rear_image', name=_('Images')), ) class Meta: @@ -354,8 +343,8 @@ class ModuleTypeForm(NetBoxModelForm): comments = CommentField() fieldsets = ( - (_('Module Type'), ('manufacturer', 'model', 'part_number', 'description', 'tags')), - (_('Weight'), ('weight', 'weight_unit')) + FieldSet('manufacturer', 'model', 'part_number', 'description', 'tags', name=_('Module Type')), + FieldSet('weight', 'weight_unit', name=_('Weight')) ) class Meta: @@ -374,9 +363,9 @@ class DeviceRoleForm(NetBoxModelForm): slug = SlugField() fieldsets = ( - (_('Device Role'), ( - 'name', 'slug', 'color', 'vm_role', 'config_template', 'description', 'tags', - )), + FieldSet( + 'name', 'slug', 'color', 'vm_role', 'config_template', 'description', 'tags', name=_('Device Role') + ), ) class Meta: @@ -403,7 +392,7 @@ class PlatformForm(NetBoxModelForm): ) fieldsets = ( - (_('Platform'), ('name', 'slug', 'manufacturer', 'config_template', 'description', 'tags')), + FieldSet('name', 'slug', 'manufacturer', 'config_template', 'description', 'tags', name=_('Platform')), ) class Meta: @@ -618,10 +607,8 @@ class ModuleForm(ModuleCommonForm, NetBoxModelForm): ) fieldsets = ( - (_('Module'), ('device', 'module_bay', 'module_type', 'status', 'description', 'tags')), - (_('Hardware'), ( - 'serial', 'asset_tag', 'replicate_components', 'adopt_components', - )), + FieldSet('device', 'module_bay', 'module_type', 'status', 'description', 'tags', name=_('Module')), + FieldSet('serial', 'asset_tag', 'replicate_components', 'adopt_components', name=_('Hardware')), ) class Meta: @@ -675,7 +662,7 @@ class PowerPanelForm(NetBoxModelForm): comments = CommentField() fieldsets = ( - ('Power Panel', ('site', 'location', 'name', 'description', 'tags')), + FieldSet('site', 'location', 'name', 'description', 'tags', name=_('Power Panel')), ) class Meta: @@ -700,9 +687,12 @@ class PowerFeedForm(TenancyForm, NetBoxModelForm): comments = CommentField() fieldsets = ( - (_('Power Feed'), ('power_panel', 'rack', 'name', 'status', 'type', 'description', 'mark_connected', 'tags')), - (_('Characteristics'), ('supply', 'voltage', 'amperage', 'phase', 'max_utilization')), - (_('Tenancy'), ('tenant_group', 'tenant')), + FieldSet( + 'power_panel', 'rack', 'name', 'status', 'type', 'description', 'mark_connected', 'tags', + name=_('Power Feed') + ), + FieldSet('supply', 'voltage', 'amperage', 'phase', 'max_utilization', name=_('Characteristics')), + FieldSet('tenant_group', 'tenant', name=_('Tenancy')), ) class Meta: @@ -849,7 +839,7 @@ class ModularComponentTemplateForm(ComponentTemplateForm): class ConsolePortTemplateForm(ModularComponentTemplateForm): fieldsets = ( - (None, ('device_type', 'module_type', 'name', 'label', 'type', 'description')), + FieldSet('device_type', 'module_type', 'name', 'label', 'type', 'description'), ) class Meta: @@ -861,7 +851,7 @@ class ConsolePortTemplateForm(ModularComponentTemplateForm): class ConsoleServerPortTemplateForm(ModularComponentTemplateForm): fieldsets = ( - (None, ('device_type', 'module_type', 'name', 'label', 'type', 'description')), + FieldSet('device_type', 'module_type', 'name', 'label', 'type', 'description'), ) class Meta: @@ -873,9 +863,9 @@ class ConsoleServerPortTemplateForm(ModularComponentTemplateForm): class PowerPortTemplateForm(ModularComponentTemplateForm): fieldsets = ( - (None, ( + FieldSet( 'device_type', 'module_type', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description', - )), + ), ) class Meta: @@ -896,7 +886,7 @@ class PowerOutletTemplateForm(ModularComponentTemplateForm): ) fieldsets = ( - (None, ('device_type', 'module_type', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description')), + FieldSet('device_type', 'module_type', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description'), ) class Meta: @@ -918,9 +908,11 @@ class InterfaceTemplateForm(ModularComponentTemplateForm): ) fieldsets = ( - (None, ('device_type', 'module_type', 'name', 'label', 'type', 'enabled', 'mgmt_only', 'description', 'bridge')), - (_('PoE'), ('poe_mode', 'poe_type')), - (_('Wireless'), ('rf_role',)), + FieldSet( + 'device_type', 'module_type', 'name', 'label', 'type', 'enabled', 'mgmt_only', 'description', 'bridge', + ), + FieldSet('poe_mode', 'poe_type', name=_('PoE')), + FieldSet('rf_role', name=_('Wireless')), ) class Meta: @@ -942,10 +934,10 @@ class FrontPortTemplateForm(ModularComponentTemplateForm): ) fieldsets = ( - (None, ( + FieldSet( 'device_type', 'module_type', 'name', 'label', 'type', 'color', 'rear_port', 'rear_port_position', 'description', - )), + ), ) class Meta: @@ -958,7 +950,7 @@ class FrontPortTemplateForm(ModularComponentTemplateForm): class RearPortTemplateForm(ModularComponentTemplateForm): fieldsets = ( - (None, ('device_type', 'module_type', 'name', 'label', 'type', 'color', 'positions', 'description')), + FieldSet('device_type', 'module_type', 'name', 'label', 'type', 'color', 'positions', 'description'), ) class Meta: @@ -970,7 +962,7 @@ class RearPortTemplateForm(ModularComponentTemplateForm): class ModuleBayTemplateForm(ComponentTemplateForm): fieldsets = ( - (None, ('device_type', 'name', 'label', 'position', 'description')), + FieldSet('device_type', 'name', 'label', 'position', 'description'), ) class Meta: @@ -982,7 +974,7 @@ class ModuleBayTemplateForm(ComponentTemplateForm): class DeviceBayTemplateForm(ComponentTemplateForm): fieldsets = ( - (None, ('device_type', 'name', 'label', 'description')), + FieldSet('device_type', 'name', 'label', 'description'), ) class Meta: @@ -1023,10 +1015,10 @@ class InventoryItemTemplateForm(ComponentTemplateForm): ) fieldsets = ( - (None, ( + FieldSet( 'device_type', 'parent', 'name', 'label', 'role', 'manufacturer', 'part_id', 'description', 'component_type', 'component_id', - )), + ), ) class Meta: @@ -1069,9 +1061,9 @@ class ModularDeviceComponentForm(DeviceComponentForm): class ConsolePortForm(ModularDeviceComponentForm): fieldsets = ( - (None, ( + FieldSet( 'device', 'module', 'name', 'label', 'type', 'speed', 'mark_connected', 'description', 'tags', - )), + ), ) class Meta: @@ -1082,11 +1074,10 @@ class ConsolePortForm(ModularDeviceComponentForm): class ConsoleServerPortForm(ModularDeviceComponentForm): - fieldsets = ( - (None, ( + FieldSet( 'device', 'module', 'name', 'label', 'type', 'speed', 'mark_connected', 'description', 'tags', - )), + ), ) class Meta: @@ -1097,12 +1088,11 @@ class ConsoleServerPortForm(ModularDeviceComponentForm): class PowerPortForm(ModularDeviceComponentForm): - fieldsets = ( - (None, ( + FieldSet( 'device', 'module', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'mark_connected', 'description', 'tags', - )), + ), ) class Meta: @@ -1124,10 +1114,10 @@ class PowerOutletForm(ModularDeviceComponentForm): ) fieldsets = ( - (None, ( + FieldSet( 'device', 'module', 'name', 'label', 'type', 'power_port', 'feed_leg', 'mark_connected', 'description', 'tags', - )), + ), ) class Meta: @@ -1223,15 +1213,18 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm): ) fieldsets = ( - (_('Interface'), ('device', 'module', 'name', 'label', 'type', 'speed', 'duplex', 'description', 'tags')), - (_('Addressing'), ('vrf', 'mac_address', 'wwn')), - (_('Operation'), ('vdcs', 'mtu', 'tx_power', 'enabled', 'mgmt_only', 'mark_connected')), - (_('Related Interfaces'), ('parent', 'bridge', 'lag')), - (_('PoE'), ('poe_mode', 'poe_type')), - (_('802.1Q Switching'), ('mode', 'vlan_group', 'untagged_vlan', 'tagged_vlans')), - (_('Wireless'), ( + FieldSet( + 'device', 'module', 'name', 'label', 'type', 'speed', 'duplex', 'description', 'tags', name=_('Interface') + ), + FieldSet('vrf', 'mac_address', 'wwn', name=_('Addressing')), + FieldSet('vdcs', 'mtu', 'tx_power', 'enabled', 'mgmt_only', 'mark_connected', name=_('Operation')), + FieldSet('parent', 'bridge', 'lag', name=_('Related Interfaces')), + FieldSet('poe_mode', 'poe_type', name=_('PoE')), + FieldSet('mode', 'vlan_group', 'untagged_vlan', 'tagged_vlans', name=_('802.1Q Switching')), + FieldSet( 'rf_role', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width', 'wireless_lan_group', 'wireless_lans', - )), + name=_('Wireless') + ), ) class Meta: @@ -1262,10 +1255,10 @@ class FrontPortForm(ModularDeviceComponentForm): ) fieldsets = ( - (None, ( + FieldSet( 'device', 'module', 'name', 'label', 'type', 'color', 'rear_port', 'rear_port_position', 'mark_connected', 'description', 'tags', - )), + ), ) class Meta: @@ -1278,9 +1271,9 @@ class FrontPortForm(ModularDeviceComponentForm): class RearPortForm(ModularDeviceComponentForm): fieldsets = ( - (None, ( + FieldSet( 'device', 'module', 'name', 'label', 'type', 'color', 'positions', 'mark_connected', 'description', 'tags', - )), + ), ) class Meta: @@ -1292,7 +1285,7 @@ class RearPortForm(ModularDeviceComponentForm): class ModuleBayForm(DeviceComponentForm): fieldsets = ( - (None, ('device', 'name', 'label', 'position', 'description', 'tags',)), + FieldSet('device', 'name', 'label', 'position', 'description', 'tags',), ) class Meta: @@ -1304,7 +1297,7 @@ class ModuleBayForm(DeviceComponentForm): class DeviceBayForm(DeviceComponentForm): fieldsets = ( - (None, ('device', 'name', 'label', 'description', 'tags',)), + FieldSet('device', 'name', 'label', 'description', 'tags',), ) class Meta: @@ -1412,19 +1405,20 @@ class InventoryItemForm(DeviceComponentForm): ) fieldsets = ( - (_('Inventory Item'), ('device', 'parent', 'name', 'label', 'role', 'description', 'tags')), - (_('Hardware'), ('manufacturer', 'part_id', 'serial', 'asset_tag')), - (_('Component Assignment'), ( + FieldSet('device', 'parent', 'name', 'label', 'role', 'description', 'tags', name=_('Inventory Item')), + FieldSet('manufacturer', 'part_id', 'serial', 'asset_tag', name=_('Hardware')), + FieldSet( TabbedGroups( - (_('Interface'), 'interface'), - (_('Console Port'), 'consoleport'), - (_('Console Server Port'), 'consoleserverport'), - (_('Front Port'), 'frontport'), - (_('Rear Port'), 'rearport'), - (_('Power Port'), 'powerport'), - (_('Power Outlet'), 'poweroutlet'), + FieldSet('interface', name=_('Interface')), + FieldSet('consoleport', name=_('Console Port')), + FieldSet('consoleserverport', name=_('Console Server Port')), + FieldSet('frontport', name=_('Front Port')), + FieldSet('rearport', name=_('Rear Port')), + FieldSet('powerport', name=_('Power Port')), + FieldSet('poweroutlet', name=_('Power Outlet')), ), - )) + name=_('Component Assignment') + ) ) class Meta: @@ -1484,9 +1478,7 @@ class InventoryItemRoleForm(NetBoxModelForm): slug = SlugField() fieldsets = ( - (_('Inventory Item Role'), ( - 'name', 'slug', 'color', 'description', 'tags', - )), + FieldSet('name', 'slug', 'color', 'description', 'tags', name=_('Inventory Item Role')), ) class Meta: @@ -1522,8 +1514,11 @@ class VirtualDeviceContextForm(TenancyForm, NetBoxModelForm): ) fieldsets = ( - (_('Virtual Device Context'), ('device', 'name', 'status', 'identifier', 'primary_ip4', 'primary_ip6', 'tags')), - (_('Tenancy'), ('tenant_group', 'tenant')) + FieldSet( + 'device', 'name', 'status', 'identifier', 'primary_ip4', 'primary_ip6', 'tags', + name=_('Virtual Device Context') + ), + FieldSet('tenant_group', 'tenant', name=_('Tenancy')) ) class Meta: diff --git a/netbox/dcim/forms/object_create.py b/netbox/dcim/forms/object_create.py index ea842508f..f811700b4 100644 --- a/netbox/dcim/forms/object_create.py +++ b/netbox/dcim/forms/object_create.py @@ -4,6 +4,7 @@ from django.utils.translation import gettext_lazy as _ from dcim.models import * from netbox.forms import NetBoxModelForm from utilities.forms.fields import DynamicModelChoiceField, DynamicModelMultipleChoiceField, ExpandableNameField +from utilities.forms.rendering import FieldSet from utilities.forms.widgets import APISelect from . import model_forms @@ -113,7 +114,7 @@ class FrontPortTemplateCreateForm(ComponentCreateForm, model_forms.FrontPortTemp # Override fieldsets from FrontPortTemplateForm to omit rear_port_position fieldsets = ( - (None, ('device_type', 'module_type', 'name', 'label', 'type', 'color', 'rear_port', 'description')), + FieldSet('device_type', 'module_type', 'name', 'label', 'type', 'color', 'rear_port', 'description'), ) class Meta(model_forms.FrontPortTemplateForm.Meta): @@ -274,9 +275,9 @@ class FrontPortCreateForm(ComponentCreateForm, model_forms.FrontPortForm): # Override fieldsets from FrontPortForm to omit rear_port_position fieldsets = ( - (None, ( + FieldSet( 'device', 'module', 'name', 'label', 'type', 'color', 'rear_port', 'mark_connected', 'description', 'tags', - )), + ), ) class Meta(model_forms.FrontPortForm.Meta): diff --git a/netbox/extras/forms/filtersets.py b/netbox/extras/forms/filtersets.py index 73751872f..d4235c465 100644 --- a/netbox/extras/forms/filtersets.py +++ b/netbox/extras/forms/filtersets.py @@ -13,6 +13,7 @@ from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES, FilterForm, add_blank_ch from utilities.forms.fields import ( ContentTypeChoiceField, ContentTypeMultipleChoiceField, DynamicModelMultipleChoiceField, TagFilterField, ) +from utilities.forms.rendering import FieldSet from utilities.forms.widgets import APISelectMultiple, DateTimePicker from virtualization.models import Cluster, ClusterGroup, ClusterType @@ -36,11 +37,11 @@ __all__ = ( class CustomFieldFilterForm(SavedFiltersMixin, FilterForm): fieldsets = ( - (None, ('q', 'filter_id')), - (_('Attributes'), ( + FieldSet('q', 'filter_id'), + FieldSet( 'type', 'related_object_type_id', 'group_name', 'weight', 'required', 'choice_set_id', 'ui_visible', - 'ui_editable', 'is_cloneable', - )), + 'ui_editable', 'is_cloneable', name=_('Attributes') + ), ) related_object_type_id = ContentTypeMultipleChoiceField( queryset=ObjectType.objects.with_feature('custom_fields'), @@ -93,8 +94,8 @@ class CustomFieldFilterForm(SavedFiltersMixin, FilterForm): class CustomFieldChoiceSetFilterForm(SavedFiltersMixin, FilterForm): fieldsets = ( - (None, ('q', 'filter_id')), - (_('Choices'), ('base_choices', 'choice')), + FieldSet('q', 'filter_id'), + FieldSet('base_choices', 'choice', name=_('Choices')), ) base_choices = forms.MultipleChoiceField( choices=CustomFieldChoiceSetBaseChoices, @@ -107,8 +108,8 @@ class CustomFieldChoiceSetFilterForm(SavedFiltersMixin, FilterForm): class CustomLinkFilterForm(SavedFiltersMixin, FilterForm): fieldsets = ( - (None, ('q', 'filter_id')), - (_('Attributes'), ('object_type', 'enabled', 'new_window', 'weight')), + FieldSet('q', 'filter_id'), + FieldSet('object_type', 'enabled', 'new_window', 'weight', name=_('Attributes')), ) object_type = ContentTypeMultipleChoiceField( label=_('Object types'), @@ -137,9 +138,9 @@ class CustomLinkFilterForm(SavedFiltersMixin, FilterForm): class ExportTemplateFilterForm(SavedFiltersMixin, FilterForm): fieldsets = ( - (None, ('q', 'filter_id')), - (_('Data'), ('data_source_id', 'data_file_id')), - (_('Attributes'), ('object_type_id', 'mime_type', 'file_extension', 'as_attachment')), + FieldSet('q', 'filter_id'), + FieldSet('data_source_id', 'data_file_id', name=_('Data')), + FieldSet('object_type_id', 'mime_type', 'file_extension', 'as_attachment', name=_('Attributes')), ) data_source_id = DynamicModelMultipleChoiceField( queryset=DataSource.objects.all(), @@ -178,8 +179,8 @@ class ExportTemplateFilterForm(SavedFiltersMixin, FilterForm): class ImageAttachmentFilterForm(SavedFiltersMixin, FilterForm): fieldsets = ( - (None, ('q', 'filter_id')), - (_('Attributes'), ('object_type_id', 'name',)), + FieldSet('q', 'filter_id'), + FieldSet('object_type_id', 'name', name=_('Attributes')), ) object_type_id = ContentTypeChoiceField( label=_('Object type'), @@ -194,8 +195,8 @@ class ImageAttachmentFilterForm(SavedFiltersMixin, FilterForm): class SavedFilterFilterForm(SavedFiltersMixin, FilterForm): fieldsets = ( - (None, ('q', 'filter_id')), - (_('Attributes'), ('object_type', 'enabled', 'shared', 'weight')), + FieldSet('q', 'filter_id'), + FieldSet('object_type', 'enabled', 'shared', 'weight', name=_('Attributes')), ) object_type = ContentTypeMultipleChoiceField( label=_('Object types'), @@ -225,8 +226,8 @@ class SavedFilterFilterForm(SavedFiltersMixin, FilterForm): class WebhookFilterForm(NetBoxModelFilterSetForm): model = Webhook fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Attributes'), ('payload_url', 'http_method', 'http_content_type')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('payload_url', 'http_method', 'http_content_type', name=_('Attributes')), ) http_content_type = forms.CharField( label=_('HTTP content type'), @@ -249,9 +250,9 @@ class EventRuleFilterForm(NetBoxModelFilterSetForm): tag = TagFilterField(model) fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Attributes'), ('object_type_id', 'action_type', 'enabled')), - (_('Events'), ('type_create', 'type_update', 'type_delete', 'type_job_start', 'type_job_end')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('object_type_id', 'action_type', 'enabled', name=_('Attributes')), + FieldSet('type_create', 'type_update', 'type_delete', 'type_job_start', 'type_job_end', name=_('Events')), ) object_type_id = ContentTypeMultipleChoiceField( queryset=ObjectType.objects.with_feature('event_rules'), @@ -323,12 +324,12 @@ class TagFilterForm(SavedFiltersMixin, FilterForm): class ConfigContextFilterForm(SavedFiltersMixin, FilterForm): fieldsets = ( - (None, ('q', 'filter_id', 'tag_id')), - (_('Data'), ('data_source_id', 'data_file_id')), - (_('Location'), ('region_id', 'site_group_id', 'site_id', 'location_id')), - (_('Device'), ('device_type_id', 'platform_id', 'role_id')), - (_('Cluster'), ('cluster_type_id', 'cluster_group_id', 'cluster_id')), - (_('Tenant'), ('tenant_group_id', 'tenant_id')) + FieldSet('q', 'filter_id', 'tag_id'), + FieldSet('data_source_id', 'data_file_id', name=_('Data')), + FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', name=_('Location')), + FieldSet('device_type_id', 'platform_id', 'role_id', name=_('Device')), + FieldSet('cluster_type_id', 'cluster_group_id', 'cluster_id', name=_('Cluster')), + FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')) ) data_source_id = DynamicModelMultipleChoiceField( queryset=DataSource.objects.all(), @@ -412,8 +413,8 @@ class ConfigContextFilterForm(SavedFiltersMixin, FilterForm): class ConfigTemplateFilterForm(SavedFiltersMixin, FilterForm): fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Data'), ('data_source_id', 'data_file_id')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('data_source_id', 'data_file_id', name=_('Data')), ) data_source_id = DynamicModelMultipleChoiceField( queryset=DataSource.objects.all(), @@ -444,9 +445,9 @@ class LocalConfigContextFilterForm(forms.Form): class JournalEntryFilterForm(NetBoxModelFilterSetForm): model = JournalEntry fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Creation'), ('created_before', 'created_after', 'created_by_id')), - (_('Attributes'), ('assigned_object_type_id', 'kind')) + FieldSet('q', 'filter_id', 'tag'), + FieldSet('created_before', 'created_after', 'created_by_id', name=_('Creation')), + FieldSet('assigned_object_type_id', 'kind', name=_('Attributes')), ) created_after = forms.DateTimeField( required=False, @@ -482,9 +483,9 @@ class JournalEntryFilterForm(NetBoxModelFilterSetForm): class ObjectChangeFilterForm(SavedFiltersMixin, FilterForm): model = ObjectChange fieldsets = ( - (None, ('q', 'filter_id')), - (_('Time'), ('time_before', 'time_after')), - (_('Attributes'), ('action', 'user_id', 'changed_object_type_id')), + FieldSet('q', 'filter_id'), + FieldSet('time_before', 'time_after', name=_('Time')), + FieldSet('action', 'user_id', 'changed_object_type_id', name=_('Attributes')), ) time_after = forms.DateTimeField( required=False, diff --git a/netbox/extras/forms/model_forms.py b/netbox/extras/forms/model_forms.py index 4e62b3ab7..680bec1e4 100644 --- a/netbox/extras/forms/model_forms.py +++ b/netbox/extras/forms/model_forms.py @@ -17,7 +17,7 @@ from utilities.forms.fields import ( CommentField, ContentTypeChoiceField, ContentTypeMultipleChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, JSONField, SlugField, ) -from utilities.forms.rendering import ObjectAttribute +from utilities.forms.rendering import FieldSet, ObjectAttribute from utilities.forms.widgets import ChoicesWidget, HTMXSelect from virtualization.models import Cluster, ClusterGroup, ClusterType @@ -55,12 +55,15 @@ class CustomFieldForm(forms.ModelForm): ) fieldsets = ( - (_('Custom Field'), ( + FieldSet( 'object_types', 'name', 'label', 'group_name', 'type', 'related_object_type', 'required', 'description', - )), - (_('Behavior'), ('search_weight', 'filter_logic', 'ui_visible', 'ui_editable', 'weight', 'is_cloneable')), - (_('Values'), ('default', 'choice_set')), - (_('Validation'), ('validation_minimum', 'validation_maximum', 'validation_regex')), + name=_('Custom Field') + ), + FieldSet( + 'search_weight', 'filter_logic', 'ui_visible', 'ui_editable', 'weight', 'is_cloneable', name=_('Behavior') + ), + FieldSet('default', 'choice_set', name=_('Values')), + FieldSet('validation_minimum', 'validation_maximum', 'validation_regex', name=_('Validation')), ) class Meta: @@ -129,8 +132,11 @@ class CustomLinkForm(forms.ModelForm): ) fieldsets = ( - (_('Custom Link'), ('name', 'object_types', 'weight', 'group_name', 'button_class', 'enabled', 'new_window')), - (_('Templates'), ('link_text', 'link_url')), + FieldSet( + 'name', 'object_types', 'weight', 'group_name', 'button_class', 'enabled', 'new_window', + name=_('Custom Link') + ), + FieldSet('link_text', 'link_url', name=_('Templates')), ) class Meta: @@ -163,9 +169,9 @@ class ExportTemplateForm(SyncedDataMixin, forms.ModelForm): ) fieldsets = ( - (_('Export Template'), ('name', 'object_types', 'description', 'template_code')), - (_('Data Source'), ('data_source', 'data_file', 'auto_sync_enabled')), - (_('Rendering'), ('mime_type', 'file_extension', 'as_attachment')), + FieldSet('name', 'object_types', 'description', 'template_code', name=_('Export Template')), + FieldSet('data_source', 'data_file', 'auto_sync_enabled', name=_('Data Source')), + FieldSet('mime_type', 'file_extension', 'as_attachment', name=_('Rendering')), ) class Meta: @@ -200,8 +206,8 @@ class SavedFilterForm(forms.ModelForm): parameters = JSONField() fieldsets = ( - (_('Saved Filter'), ('name', 'slug', 'object_types', 'description', 'weight', 'enabled', 'shared')), - (_('Parameters'), ('parameters',)), + FieldSet('name', 'slug', 'object_types', 'description', 'weight', 'enabled', 'shared', name=_('Saved Filter')), + FieldSet('parameters', name=_('Parameters')), ) class Meta: @@ -232,11 +238,12 @@ class BookmarkForm(forms.ModelForm): class WebhookForm(NetBoxModelForm): fieldsets = ( - (_('Webhook'), ('name', 'description', 'tags',)), - (_('HTTP Request'), ( + FieldSet('name', 'description', 'tags', name=_('Webhook')), + FieldSet( 'payload_url', 'http_method', 'http_content_type', 'additional_headers', 'body_template', 'secret', - )), - (_('SSL'), ('ssl_verification', 'ca_file_path')), + name=_('HTTP Request') + ), + FieldSet('ssl_verification', 'ca_file_path', name=_('SSL')), ) class Meta: @@ -267,12 +274,13 @@ class EventRuleForm(NetBoxModelForm): ) fieldsets = ( - (_('Event Rule'), ('name', 'description', 'object_types', 'enabled', 'tags')), - (_('Events'), ('type_create', 'type_update', 'type_delete', 'type_job_start', 'type_job_end')), - (_('Conditions'), ('conditions',)), - (_('Action'), ( + FieldSet('name', 'description', 'object_types', 'enabled', 'tags', name=_('Event Rule')), + FieldSet('type_create', 'type_update', 'type_delete', 'type_job_start', 'type_job_end', name=_('Events')), + FieldSet('conditions', name=_('Conditions')), + FieldSet( 'action_type', 'action_choice', 'action_object_type', 'action_object_id', 'action_data', - )), + name=_('Action') + ), ) class Meta: @@ -361,7 +369,7 @@ class TagForm(forms.ModelForm): ) fieldsets = ( - ('Tag', ('name', 'slug', 'color', 'description', 'object_types')), + FieldSet('name', 'slug', 'color', 'description', 'object_types', name=_('Tag')), ) class Meta: @@ -443,12 +451,13 @@ class ConfigContextForm(SyncedDataMixin, forms.ModelForm): ) fieldsets = ( - (_('Config Context'), ('name', 'weight', 'description', 'data', 'is_active')), - (_('Data Source'), ('data_source', 'data_file', 'auto_sync_enabled')), - (_('Assignment'), ( + FieldSet('name', 'weight', 'description', 'data', 'is_active', name=_('Config Context')), + FieldSet('data_source', 'data_file', 'auto_sync_enabled', name=_('Data Source')), + FieldSet( 'regions', 'site_groups', 'sites', 'locations', 'device_types', 'roles', 'platforms', 'cluster_types', 'cluster_groups', 'clusters', 'tenant_groups', 'tenants', 'tags', - )), + name=_('Assignment') + ), ) class Meta: @@ -495,9 +504,9 @@ class ConfigTemplateForm(SyncedDataMixin, forms.ModelForm): ) fieldsets = ( - (_('Config Template'), ('name', 'description', 'environment_params', 'tags')), - (_('Content'), ('template_code',)), - (_('Data Source'), ('data_source', 'data_file', 'auto_sync_enabled')), + FieldSet('name', 'description', 'environment_params', 'tags', name=_('Config Template')), + FieldSet('template_code', name=_('Content')), + FieldSet('data_source', 'data_file', 'auto_sync_enabled', name=_('Data Source')), ) class Meta: @@ -528,7 +537,7 @@ class ConfigTemplateForm(SyncedDataMixin, forms.ModelForm): class ImageAttachmentForm(forms.ModelForm): fieldsets = ( - (None, (ObjectAttribute('parent'), 'name', 'image')), + FieldSet(ObjectAttribute('parent'), 'name', 'image'), ) class Meta: diff --git a/netbox/ipam/forms/bulk_edit.py b/netbox/ipam/forms/bulk_edit.py index 72d57e941..c7f64ab1d 100644 --- a/netbox/ipam/forms/bulk_edit.py +++ b/netbox/ipam/forms/bulk_edit.py @@ -13,6 +13,7 @@ from utilities.forms import add_blank_choice from utilities.forms.fields import ( CommentField, ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, NumericArrayField, ) +from utilities.forms.rendering import FieldSet from utilities.forms.widgets import BulkEditNullBooleanSelect from virtualization.models import Cluster, ClusterGroup @@ -55,7 +56,7 @@ class VRFBulkEditForm(NetBoxModelBulkEditForm): model = VRF fieldsets = ( - (None, ('tenant', 'enforce_unique', 'description')), + FieldSet('tenant', 'enforce_unique', 'description'), ) nullable_fields = ('tenant', 'description', 'comments') @@ -75,7 +76,7 @@ class RouteTargetBulkEditForm(NetBoxModelBulkEditForm): model = RouteTarget fieldsets = ( - (None, ('tenant', 'description')), + FieldSet('tenant', 'description'), ) nullable_fields = ('tenant', 'description', 'comments') @@ -94,7 +95,7 @@ class RIRBulkEditForm(NetBoxModelBulkEditForm): model = RIR fieldsets = ( - (None, ('is_private', 'description')), + FieldSet('is_private', 'description'), ) nullable_fields = ('is_private', 'description') @@ -118,7 +119,7 @@ class ASNRangeBulkEditForm(NetBoxModelBulkEditForm): model = ASNRange fieldsets = ( - (None, ('rir', 'tenant', 'description')), + FieldSet('rir', 'tenant', 'description'), ) nullable_fields = ('description',) @@ -148,7 +149,7 @@ class ASNBulkEditForm(NetBoxModelBulkEditForm): model = ASN fieldsets = ( - (None, ('sites', 'rir', 'tenant', 'description')), + FieldSet('sites', 'rir', 'tenant', 'description'), ) nullable_fields = ('tenant', 'description', 'comments') @@ -177,7 +178,7 @@ class AggregateBulkEditForm(NetBoxModelBulkEditForm): model = Aggregate fieldsets = ( - (None, ('rir', 'tenant', 'date_added', 'description')), + FieldSet('rir', 'tenant', 'date_added', 'description'), ) nullable_fields = ('date_added', 'description', 'comments') @@ -195,7 +196,7 @@ class RoleBulkEditForm(NetBoxModelBulkEditForm): model = Role fieldsets = ( - (None, ('weight', 'description')), + FieldSet('weight', 'description'), ) nullable_fields = ('description',) @@ -265,9 +266,9 @@ class PrefixBulkEditForm(NetBoxModelBulkEditForm): model = Prefix fieldsets = ( - (None, ('tenant', 'status', 'role', 'description')), - (_('Site'), ('region', 'site_group', 'site')), - (_('Addressing'), ('vrf', 'prefix_length', 'is_pool', 'mark_utilized')), + FieldSet('tenant', 'status', 'role', 'description'), + FieldSet('region', 'site_group', 'site', name=_('Site')), + FieldSet('vrf', 'prefix_length', 'is_pool', 'mark_utilized', name=_('Addressing')), ) nullable_fields = ( 'site', 'vrf', 'tenant', 'role', 'description', 'comments', @@ -309,7 +310,7 @@ class IPRangeBulkEditForm(NetBoxModelBulkEditForm): model = IPRange fieldsets = ( - (None, ('status', 'role', 'vrf', 'tenant', 'mark_utilized', 'description')), + FieldSet('status', 'role', 'vrf', 'tenant', 'mark_utilized', 'description'), ) nullable_fields = ( 'vrf', 'tenant', 'role', 'description', 'comments', @@ -357,8 +358,8 @@ class IPAddressBulkEditForm(NetBoxModelBulkEditForm): model = IPAddress fieldsets = ( - (None, ('status', 'role', 'tenant', 'description')), - (_('Addressing'), ('vrf', 'mask_length', 'dns_name')), + FieldSet('status', 'role', 'tenant', 'description'), + FieldSet('vrf', 'mask_length', 'dns_name', name=_('Addressing')), ) nullable_fields = ( 'vrf', 'role', 'tenant', 'dns_name', 'description', 'comments', @@ -400,8 +401,8 @@ class FHRPGroupBulkEditForm(NetBoxModelBulkEditForm): model = FHRPGroup fieldsets = ( - (None, ('protocol', 'group_id', 'name', 'description')), - (_('Authentication'), ('auth_type', 'auth_key')), + FieldSet('protocol', 'group_id', 'name', 'description'), + FieldSet('auth_type', 'auth_key', name=_('Authentication')), ) nullable_fields = ('auth_type', 'auth_key', 'name', 'description', 'comments') @@ -485,8 +486,10 @@ class VLANGroupBulkEditForm(NetBoxModelBulkEditForm): model = VLANGroup fieldsets = ( - (None, ('site', 'min_vid', 'max_vid', 'description')), - (_('Scope'), ('scope_type', 'region', 'sitegroup', 'site', 'location', 'rack', 'clustergroup', 'cluster')), + FieldSet('site', 'min_vid', 'max_vid', 'description'), + FieldSet( + 'scope_type', 'region', 'sitegroup', 'site', 'location', 'rack', 'clustergroup', 'cluster', name=_('Scope') + ), ) nullable_fields = ('description',) @@ -556,8 +559,8 @@ class VLANBulkEditForm(NetBoxModelBulkEditForm): model = VLAN fieldsets = ( - (None, ('status', 'role', 'tenant', 'description')), - (_('Site & Group'), ('region', 'site_group', 'site', 'group')), + FieldSet('status', 'role', 'tenant', 'description'), + FieldSet('region', 'site_group', 'site', 'group', name=_('Site & Group')), ) nullable_fields = ( 'site', 'group', 'tenant', 'role', 'description', 'comments', @@ -587,7 +590,7 @@ class ServiceTemplateBulkEditForm(NetBoxModelBulkEditForm): model = ServiceTemplate fieldsets = ( - (None, ('protocol', 'ports', 'description')), + FieldSet('protocol', 'ports', 'description'), ) nullable_fields = ('description', 'comments') diff --git a/netbox/ipam/forms/filtersets.py b/netbox/ipam/forms/filtersets.py index cf2e4d46e..6610bcaf3 100644 --- a/netbox/ipam/forms/filtersets.py +++ b/netbox/ipam/forms/filtersets.py @@ -9,6 +9,7 @@ from netbox.forms import NetBoxModelFilterSetForm from tenancy.forms import TenancyFilterForm from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES, add_blank_choice from utilities.forms.fields import DynamicModelChoiceField, DynamicModelMultipleChoiceField, TagFilterField +from utilities.forms.rendering import FieldSet from virtualization.models import VirtualMachine from vpn.models import L2VPN @@ -42,9 +43,9 @@ IPADDRESS_MASK_LENGTH_CHOICES = add_blank_choice([ class VRFFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = VRF fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Route Targets'), ('import_target_id', 'export_target_id')), - (_('Tenant'), ('tenant_group_id', 'tenant_id')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('import_target_id', 'export_target_id', name=_('Route Targets')), + FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), ) import_target_id = DynamicModelMultipleChoiceField( queryset=RouteTarget.objects.all(), @@ -62,9 +63,9 @@ class VRFFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): class RouteTargetFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = RouteTarget fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('VRF'), ('importing_vrf_id', 'exporting_vrf_id')), - (_('Tenant'), ('tenant_group_id', 'tenant_id')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('importing_vrf_id', 'exporting_vrf_id', name=_('VRF')), + FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), ) importing_vrf_id = DynamicModelMultipleChoiceField( queryset=VRF.objects.all(), @@ -94,9 +95,9 @@ class RIRFilterForm(NetBoxModelFilterSetForm): class AggregateFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = Aggregate fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Attributes'), ('family', 'rir_id')), - (_('Tenant'), ('tenant_group_id', 'tenant_id')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('family', 'rir_id', name=_('Attributes')), + FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), ) family = forms.ChoiceField( required=False, @@ -114,9 +115,9 @@ class AggregateFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): class ASNRangeFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = ASNRange fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Range'), ('rir_id', 'start', 'end')), - (_('Tenant'), ('tenant_group_id', 'tenant_id')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('rir_id', 'start', 'end', name=_('Range')), + FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), ) rir_id = DynamicModelMultipleChoiceField( queryset=RIR.objects.all(), @@ -137,9 +138,9 @@ class ASNRangeFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): class ASNFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = ASN fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Assignment'), ('rir_id', 'site_id')), - (_('Tenant'), ('tenant_group_id', 'tenant_id')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('rir_id', 'site_id', name=_('Assignment')), + FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), ) rir_id = DynamicModelMultipleChoiceField( queryset=RIR.objects.all(), @@ -162,11 +163,14 @@ class RoleFilterForm(NetBoxModelFilterSetForm): class PrefixFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = Prefix fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Addressing'), ('within_include', 'family', 'status', 'role_id', 'mask_length', 'is_pool', 'mark_utilized')), - (_('VRF'), ('vrf_id', 'present_in_vrf_id')), - (_('Location'), ('region_id', 'site_group_id', 'site_id')), - (_('Tenant'), ('tenant_group_id', 'tenant_id')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet( + 'within_include', 'family', 'status', 'role_id', 'mask_length', 'is_pool', 'mark_utilized', + name=_('Addressing') + ), + FieldSet('vrf_id', 'present_in_vrf_id', name=_('VRF')), + FieldSet('region_id', 'site_group_id', 'site_id', name=_('Location')), + FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), ) mask_length__lte = forms.IntegerField( widget=forms.HiddenInput() @@ -251,9 +255,9 @@ class PrefixFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): class IPRangeFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = IPRange fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Attributes'), ('family', 'vrf_id', 'status', 'role_id', 'mark_utilized')), - (_('Tenant'), ('tenant_group_id', 'tenant_id')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('family', 'vrf_id', 'status', 'role_id', 'mark_utilized', name=_('Attributes')), + FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), ) family = forms.ChoiceField( required=False, @@ -290,11 +294,14 @@ class IPRangeFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): class IPAddressFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = IPAddress fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Attributes'), ('parent', 'family', 'status', 'role', 'mask_length', 'assigned_to_interface', 'dns_name')), - (_('VRF'), ('vrf_id', 'present_in_vrf_id')), - (_('Tenant'), ('tenant_group_id', 'tenant_id')), - (_('Device/VM'), ('device_id', 'virtual_machine_id')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet( + 'parent', 'family', 'status', 'role', 'mask_length', 'assigned_to_interface', 'dns_name', + name=_('Attributes') + ), + FieldSet('vrf_id', 'present_in_vrf_id', name=_('VRF')), + FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), + FieldSet('device_id', 'virtual_machine_id', name=_('Device/VM')), ) selector_fields = ('filter_id', 'q', 'region_id', 'group_id', 'parent', 'status', 'role') parent = forms.CharField( @@ -364,9 +371,9 @@ class IPAddressFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): class FHRPGroupFilterForm(NetBoxModelFilterSetForm): model = FHRPGroup fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Attributes'), ('name', 'protocol', 'group_id')), - (_('Authentication'), ('auth_type', 'auth_key')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('name', 'protocol', 'group_id', name=_('Attributes')), + FieldSet('auth_type', 'auth_key', name=_('Authentication')), ) name = forms.CharField( label=_('Name'), @@ -396,9 +403,9 @@ class FHRPGroupFilterForm(NetBoxModelFilterSetForm): class VLANGroupFilterForm(NetBoxModelFilterSetForm): fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Location'), ('region', 'sitegroup', 'site', 'location', 'rack')), - (_('VLAN ID'), ('min_vid', 'max_vid')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('region', 'sitegroup', 'site', 'location', 'rack', name=_('Location')), + FieldSet('min_vid', 'max_vid', name=_('VLAN ID')), ) model = VLANGroup region = DynamicModelMultipleChoiceField( @@ -444,10 +451,10 @@ class VLANGroupFilterForm(NetBoxModelFilterSetForm): class VLANFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = VLAN fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Location'), ('region_id', 'site_group_id', 'site_id')), - (_('Attributes'), ('group_id', 'status', 'role_id', 'vid', 'l2vpn_id')), - (_('Tenant'), ('tenant_group_id', 'tenant_id')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('region_id', 'site_group_id', 'site_id', name=_('Location')), + FieldSet('group_id', 'status', 'role_id', 'vid', 'l2vpn_id', name=_('Attributes')), + FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), ) selector_fields = ('filter_id', 'q', 'site_id') region_id = DynamicModelMultipleChoiceField( @@ -504,8 +511,8 @@ class VLANFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): class ServiceTemplateFilterForm(NetBoxModelFilterSetForm): model = ServiceTemplate fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Attributes'), ('protocol', 'port')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('protocol', 'port', name=_('Attributes')), ) protocol = forms.ChoiceField( label=_('Protocol'), @@ -522,9 +529,9 @@ class ServiceTemplateFilterForm(NetBoxModelFilterSetForm): class ServiceFilterForm(ServiceTemplateFilterForm): model = Service fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Attributes'), ('protocol', 'port')), - (_('Assignment'), ('device_id', 'virtual_machine_id')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('protocol', 'port', name=_('Attributes')), + FieldSet('device_id', 'virtual_machine_id', name=_('Assignment')), ) device_id = DynamicModelMultipleChoiceField( queryset=Device.objects.all(), diff --git a/netbox/ipam/forms/model_forms.py b/netbox/ipam/forms/model_forms.py index 0aba37fb9..0db9576f1 100644 --- a/netbox/ipam/forms/model_forms.py +++ b/netbox/ipam/forms/model_forms.py @@ -16,7 +16,7 @@ from utilities.forms.fields import ( CommentField, ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, NumericArrayField, SlugField, ) -from utilities.forms.rendering import InlineFields, ObjectAttribute, TabbedGroups +from utilities.forms.rendering import FieldSet, InlineFields, ObjectAttribute, TabbedGroups from utilities.forms.widgets import DatePicker from virtualization.models import Cluster, ClusterGroup, VirtualMachine, VMInterface @@ -57,9 +57,9 @@ class VRFForm(TenancyForm, NetBoxModelForm): comments = CommentField() fieldsets = ( - (_('VRF'), ('name', 'rd', 'enforce_unique', 'description', 'tags')), - (_('Route Targets'), ('import_targets', 'export_targets')), - (_('Tenancy'), ('tenant_group', 'tenant')), + FieldSet('name', 'rd', 'enforce_unique', 'description', 'tags', name=_('VRF')), + FieldSet('import_targets', 'export_targets', name=_('Route Targets')), + FieldSet('tenant_group', 'tenant', name=_('Tenancy')), ) class Meta: @@ -75,8 +75,8 @@ class VRFForm(TenancyForm, NetBoxModelForm): class RouteTargetForm(TenancyForm, NetBoxModelForm): fieldsets = ( - ('Route Target', ('name', 'description', 'tags')), - ('Tenancy', ('tenant_group', 'tenant')), + FieldSet('name', 'description', 'tags', name=_('Route Target')), + FieldSet('tenant_group', 'tenant', name=_('Tenancy')), ) comments = CommentField() @@ -91,9 +91,7 @@ class RIRForm(NetBoxModelForm): slug = SlugField() fieldsets = ( - (_('RIR'), ( - 'name', 'slug', 'is_private', 'description', 'tags', - )), + FieldSet('name', 'slug', 'is_private', 'description', 'tags', name=_('RIR')), ) class Meta: @@ -111,8 +109,8 @@ class AggregateForm(TenancyForm, NetBoxModelForm): comments = CommentField() fieldsets = ( - (_('Aggregate'), ('prefix', 'rir', 'date_added', 'description', 'tags')), - (_('Tenancy'), ('tenant_group', 'tenant')), + FieldSet('prefix', 'rir', 'date_added', 'description', 'tags', name=_('Aggregate')), + FieldSet('tenant_group', 'tenant', name=_('Tenancy')), ) class Meta: @@ -132,8 +130,8 @@ class ASNRangeForm(TenancyForm, NetBoxModelForm): ) slug = SlugField() fieldsets = ( - (_('ASN Range'), ('name', 'slug', 'rir', 'start', 'end', 'description', 'tags')), - (_('Tenancy'), ('tenant_group', 'tenant')), + FieldSet('name', 'slug', 'rir', 'start', 'end', 'description', 'tags', name=_('ASN Range')), + FieldSet('tenant_group', 'tenant', name=_('Tenancy')), ) class Meta: @@ -156,8 +154,8 @@ class ASNForm(TenancyForm, NetBoxModelForm): comments = CommentField() fieldsets = ( - (_('ASN'), ('asn', 'rir', 'sites', 'description', 'tags')), - (_('Tenancy'), ('tenant_group', 'tenant')), + FieldSet('asn', 'rir', 'sites', 'description', 'tags', name=_('ASN')), + FieldSet('tenant_group', 'tenant', name=_('Tenancy')), ) class Meta: @@ -185,9 +183,7 @@ class RoleForm(NetBoxModelForm): slug = SlugField() fieldsets = ( - (_('Role'), ( - 'name', 'slug', 'weight', 'description', 'tags', - )), + FieldSet('name', 'slug', 'weight', 'description', 'tags', name=_('Role')), ) class Meta: @@ -227,9 +223,11 @@ class PrefixForm(TenancyForm, NetBoxModelForm): comments = CommentField() fieldsets = ( - (_('Prefix'), ('prefix', 'status', 'vrf', 'role', 'is_pool', 'mark_utilized', 'description', 'tags')), - (_('Site/VLAN Assignment'), ('site', 'vlan')), - (_('Tenancy'), ('tenant_group', 'tenant')), + FieldSet( + 'prefix', 'status', 'vrf', 'role', 'is_pool', 'mark_utilized', 'description', 'tags', name=_('Prefix') + ), + FieldSet('site', 'vlan', name=_('Site/VLAN Assignment')), + FieldSet('tenant_group', 'tenant', name=_('Tenancy')), ) class Meta: @@ -254,8 +252,11 @@ class IPRangeForm(TenancyForm, NetBoxModelForm): comments = CommentField() fieldsets = ( - (_('IP Range'), ('vrf', 'start_address', 'end_address', 'role', 'status', 'mark_utilized', 'description', 'tags')), - (_('Tenancy'), ('tenant_group', 'tenant')), + FieldSet( + 'vrf', 'start_address', 'end_address', 'role', 'status', 'mark_utilized', 'description', 'tags', + name=_('IP Range') + ), + FieldSet('tenant_group', 'tenant', name=_('Tenancy')), ) class Meta: @@ -309,17 +310,17 @@ class IPAddressForm(TenancyForm, NetBoxModelForm): comments = CommentField() fieldsets = ( - (_('IP Address'), ('address', 'status', 'role', 'vrf', 'dns_name', 'description', 'tags')), - (_('Tenancy'), ('tenant_group', 'tenant')), - (_('Assignment'), ( + FieldSet('address', 'status', 'role', 'vrf', 'dns_name', 'description', 'tags', name=_('IP Address')), + FieldSet('tenant_group', 'tenant', name=_('Tenancy')), + FieldSet( TabbedGroups( - (_('Device'), 'interface'), - (_('Virtual Machine'), 'vminterface'), - (_('FHRP Group'), 'fhrpgroup'), + FieldSet('interface', name=_('Device')), + FieldSet('vminterface', name=_('Virtual Machine')), + FieldSet('fhrpgroup', name=_('FHRP Group')), ), - 'primary_for_parent', - )), - (_('NAT IP (Inside)'), ('nat_inside',)), + 'primary_for_parent', name=_('Assignment') + ), + FieldSet('nat_inside', name=_('NAT IP (Inside)')), ) class Meta: @@ -458,9 +459,9 @@ class FHRPGroupForm(NetBoxModelForm): comments = CommentField() fieldsets = ( - (_('FHRP Group'), ('protocol', 'group_id', 'name', 'description', 'tags')), - (_('Authentication'), ('auth_type', 'auth_key')), - (_('Virtual IP Address'), ('ip_vrf', 'ip_address', 'ip_status')) + FieldSet('protocol', 'group_id', 'name', 'description', 'tags', name=_('FHRP Group')), + FieldSet('auth_type', 'auth_key', name=_('Authentication')), + FieldSet('ip_vrf', 'ip_address', 'ip_status', name=_('Virtual IP Address')) ) class Meta: @@ -518,7 +519,7 @@ class FHRPGroupAssignmentForm(forms.ModelForm): ) fieldsets = ( - (None, (ObjectAttribute('interface'), 'group', 'priority')), + FieldSet(ObjectAttribute('interface'), 'group', 'priority'), ) class Meta: @@ -606,9 +607,12 @@ class VLANGroupForm(NetBoxModelForm): slug = SlugField() fieldsets = ( - (_('VLAN Group'), ('name', 'slug', 'description', 'tags')), - (_('Child VLANs'), ('min_vid', 'max_vid')), - (_('Scope'), ('scope_type', 'region', 'sitegroup', 'site', 'location', 'rack', 'clustergroup', 'cluster')), + FieldSet('name', 'slug', 'description', 'tags', name=_('VLAN Group')), + FieldSet('min_vid', 'max_vid', name=_('Child VLANs')), + FieldSet( + 'scope_type', 'region', 'sitegroup', 'site', 'location', 'rack', 'clustergroup', 'cluster', + name=_('Scope') + ), ) class Meta: @@ -681,9 +685,7 @@ class ServiceTemplateForm(NetBoxModelForm): comments = CommentField() fieldsets = ( - (_('Service Template'), ( - 'name', 'protocol', 'ports', 'description', 'tags', - )), + FieldSet('name', 'protocol', 'ports', 'description', 'tags', name=_('Service Template')), ) class Meta: @@ -724,17 +726,15 @@ class ServiceForm(NetBoxModelForm): comments = CommentField() fieldsets = ( - (_('Service'), ( + FieldSet( TabbedGroups( - (_('Device'), 'device'), - (_('Virtual Machine'), 'virtual_machine'), + FieldSet('device', name=_('Device')), + FieldSet('virtual_machine', name=_('Virtual Machine')), ), 'name', InlineFields('protocol', 'ports', label=_('Port(s)')), - 'ipaddresses', - 'description', - 'tags', - )), + 'ipaddresses', 'description', 'tags', name=_('Service') + ), ) class Meta: @@ -752,19 +752,17 @@ class ServiceCreateForm(ServiceForm): ) fieldsets = ( - (_('Service'), ( + FieldSet( TabbedGroups( - (_('Device'), 'device'), - (_('Virtual Machine'), 'virtual_machine'), + FieldSet('device', name=_('Device')), + FieldSet('virtual_machine', name=_('Virtual Machine')), ), TabbedGroups( - (_('From Template'), 'service_template'), - (_('Custom'), 'name', 'protocol', 'ports'), + FieldSet('service_template', name=_('From Template')), + FieldSet('name', 'protocol', 'ports', name=_('Custom')), ), - 'ipaddresses', - 'description', - 'tags', - )), + 'ipaddresses', 'description', 'tags', name=_('Service') + ), ) class Meta(ServiceForm.Meta): diff --git a/netbox/netbox/forms/base.py b/netbox/netbox/forms/base.py index 85064e79d..f63f56ff5 100644 --- a/netbox/netbox/forms/base.py +++ b/netbox/netbox/forms/base.py @@ -24,7 +24,7 @@ class NetBoxModelForm(CheckLastUpdatedMixin, CustomFieldsMixin, TagsMixin, forms Base form for creating & editing NetBox models. Extends Django's ModelForm to add support for custom fields. Attributes: - fieldsets: An iterable of two-tuples which define a heading and field set to display per section of + fieldsets: An iterable of FieldSets which define a name and set of fields to display per section of the rendered form (optional). If not defined, the all fields will be rendered as a single section. """ fieldsets = () diff --git a/netbox/templates/generic/bulk_edit.html b/netbox/templates/generic/bulk_edit.html index 10788d62f..ebb0fbc0e 100644 --- a/netbox/templates/generic/bulk_edit.html +++ b/netbox/templates/generic/bulk_edit.html @@ -49,14 +49,18 @@ Context: {% if form.fieldsets %} {# Render grouped fields according to declared fieldsets #} - {% for group, fields in form.fieldsets %} + {% for fieldset in form.fieldsets %}
- {% if group %}{{ group }}{% else %}{{ model|meta:"verbose_name"|bettertitle }}{% endif %} + {% if fieldset.name %} + {{ fieldset.name }} + {% else %} + {{ model|meta:"verbose_name"|bettertitle }} + {% endif %}
- {% for name in fields %} + {% for name in fieldset.fields %} {% with field=form|getfield:name %} {% if field.name in form.nullable_fields %} {% render_field field bulk_nullable=True %} diff --git a/netbox/templates/inc/filter_list.html b/netbox/templates/inc/filter_list.html index ac87f252d..407add929 100644 --- a/netbox/templates/inc/filter_list.html +++ b/netbox/templates/inc/filter_list.html @@ -9,14 +9,14 @@ {{ field }} {% endfor %} {# List filters by group #} - {% for heading, fields in filter_form.fieldsets %} + {% for fieldset in filter_form.fieldsets %}
- {% if heading %} + {% if fieldset.name %}
- {{ heading }} + {{ fieldset.name }}
{% endif %} - {% for name in fields %} + {% for name in fieldset.fields %} {% with field=filter_form|get_item:name %} {% render_field field %} {% endwith %} diff --git a/netbox/tenancy/forms/bulk_edit.py b/netbox/tenancy/forms/bulk_edit.py index 49866ca3e..5af3f22ac 100644 --- a/netbox/tenancy/forms/bulk_edit.py +++ b/netbox/tenancy/forms/bulk_edit.py @@ -6,6 +6,7 @@ from tenancy.choices import ContactPriorityChoices from tenancy.models import * from utilities.forms import add_blank_choice from utilities.forms.fields import CommentField, DynamicModelChoiceField +from utilities.forms.rendering import FieldSet __all__ = ( 'ContactAssignmentBulkEditForm', @@ -46,7 +47,7 @@ class TenantBulkEditForm(NetBoxModelBulkEditForm): model = Tenant fieldsets = ( - (None, ('group',)), + FieldSet('group'), ) nullable_fields = ('group',) @@ -69,7 +70,7 @@ class ContactGroupBulkEditForm(NetBoxModelBulkEditForm): model = ContactGroup fieldsets = ( - (None, ('parent', 'description')), + FieldSet('parent', 'description'), ) nullable_fields = ('parent', 'description') @@ -83,7 +84,7 @@ class ContactRoleBulkEditForm(NetBoxModelBulkEditForm): model = ContactRole fieldsets = ( - (None, ('description',)), + FieldSet('description'), ) nullable_fields = ('description',) @@ -126,7 +127,7 @@ class ContactBulkEditForm(NetBoxModelBulkEditForm): model = Contact fieldsets = ( - (None, ('group', 'title', 'phone', 'email', 'address', 'link', 'description')), + FieldSet('group', 'title', 'phone', 'email', 'address', 'link', 'description'), ) nullable_fields = ('group', 'title', 'phone', 'email', 'address', 'link', 'description', 'comments') @@ -150,6 +151,6 @@ class ContactAssignmentBulkEditForm(NetBoxModelBulkEditForm): model = ContactAssignment fieldsets = ( - (None, ('contact', 'role', 'priority')), + FieldSet('contact', 'role', 'priority'), ) nullable_fields = ('priority',) diff --git a/netbox/tenancy/forms/filtersets.py b/netbox/tenancy/forms/filtersets.py index fbd0f2ad0..960ca45b1 100644 --- a/netbox/tenancy/forms/filtersets.py +++ b/netbox/tenancy/forms/filtersets.py @@ -9,6 +9,7 @@ from tenancy.forms import ContactModelFilterForm from utilities.forms.fields import ( ContentTypeMultipleChoiceField, DynamicModelMultipleChoiceField, TagFilterField, ) +from utilities.forms.rendering import FieldSet __all__ = ( 'ContactAssignmentFilterForm', @@ -37,8 +38,8 @@ class TenantGroupFilterForm(NetBoxModelFilterSetForm): class TenantFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm): model = Tenant fieldsets = ( - (None, ('q', 'filter_id', 'tag', 'group_id')), - ('Contacts', ('contact', 'contact_role', 'contact_group')) + FieldSet('q', 'filter_id', 'tag', 'group_id'), + FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')) ) group_id = DynamicModelMultipleChoiceField( queryset=TenantGroup.objects.all(), @@ -82,8 +83,8 @@ class ContactFilterForm(NetBoxModelFilterSetForm): class ContactAssignmentFilterForm(NetBoxModelFilterSetForm): model = ContactAssignment fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Assignment'), ('object_type_id', 'group_id', 'contact_id', 'role_id', 'priority')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('object_type_id', 'group_id', 'contact_id', 'role_id', 'priority', name=_('Assignment')), ) object_type_id = ContentTypeMultipleChoiceField( queryset=ObjectType.objects.with_feature('contacts'), diff --git a/netbox/tenancy/forms/model_forms.py b/netbox/tenancy/forms/model_forms.py index 7dcb4e433..bc18deed6 100644 --- a/netbox/tenancy/forms/model_forms.py +++ b/netbox/tenancy/forms/model_forms.py @@ -4,7 +4,7 @@ from django.utils.translation import gettext_lazy as _ from netbox.forms import NetBoxModelForm from tenancy.models import * from utilities.forms.fields import CommentField, DynamicModelChoiceField, SlugField -from utilities.forms.rendering import ObjectAttribute +from utilities.forms.rendering import FieldSet, ObjectAttribute __all__ = ( 'ContactAssignmentForm', @@ -29,9 +29,7 @@ class TenantGroupForm(NetBoxModelForm): slug = SlugField() fieldsets = ( - (_('Tenant Group'), ( - 'parent', 'name', 'slug', 'description', 'tags', - )), + FieldSet('parent', 'name', 'slug', 'description', 'tags', name=_('Tenant Group')), ) class Meta: @@ -51,7 +49,7 @@ class TenantForm(NetBoxModelForm): comments = CommentField() fieldsets = ( - (_('Tenant'), ('name', 'slug', 'group', 'description', 'tags')), + FieldSet('name', 'slug', 'group', 'description', 'tags', name=_('Tenant')), ) class Meta: @@ -74,9 +72,7 @@ class ContactGroupForm(NetBoxModelForm): slug = SlugField() fieldsets = ( - (_('Contact Group'), ( - 'parent', 'name', 'slug', 'description', 'tags', - )), + FieldSet('parent', 'name', 'slug', 'description', 'tags', name=_('Contact Group')), ) class Meta: @@ -88,9 +84,7 @@ class ContactRoleForm(NetBoxModelForm): slug = SlugField() fieldsets = ( - (_('Contact Role'), ( - 'name', 'slug', 'description', 'tags', - )), + FieldSet('name', 'slug', 'description', 'tags', name=_('Contact Role')), ) class Meta: @@ -107,7 +101,10 @@ class ContactForm(NetBoxModelForm): comments = CommentField() fieldsets = ( - (_('Contact'), ('group', 'name', 'title', 'phone', 'email', 'address', 'link', 'description', 'tags')), + FieldSet( + 'group', 'name', 'title', 'phone', 'email', 'address', 'link', 'description', 'tags', + name=_('Contact') + ), ) class Meta: @@ -142,7 +139,7 @@ class ContactAssignmentForm(NetBoxModelForm): ) fieldsets = ( - (None, (ObjectAttribute('object'), 'group', 'contact', 'role', 'priority', 'tags')), + FieldSet(ObjectAttribute('object'), 'group', 'contact', 'role', 'priority', 'tags'), ) class Meta: diff --git a/netbox/users/forms/bulk_edit.py b/netbox/users/forms/bulk_edit.py index c56beff14..a26842d09 100644 --- a/netbox/users/forms/bulk_edit.py +++ b/netbox/users/forms/bulk_edit.py @@ -6,6 +6,7 @@ from ipam.formfields import IPNetworkFormField from ipam.validators import prefix_validator from users.models import * from utilities.forms import BulkEditForm +from utilities.forms.rendering import FieldSet from utilities.forms.widgets import BulkEditNullBooleanSelect, DateTimePicker __all__ = ( @@ -48,7 +49,7 @@ class UserBulkEditForm(forms.Form): model = User fieldsets = ( - (None, ('first_name', 'last_name', 'is_active', 'is_staff', 'is_superuser')), + FieldSet('first_name', 'last_name', 'is_active', 'is_staff', 'is_superuser'), ) nullable_fields = ('first_name', 'last_name') @@ -71,7 +72,7 @@ class ObjectPermissionBulkEditForm(forms.Form): model = ObjectPermission fieldsets = ( - (None, ('enabled', 'description')), + FieldSet('enabled', 'description'), ) nullable_fields = ('description',) @@ -104,7 +105,7 @@ class TokenBulkEditForm(BulkEditForm): model = Token fieldsets = ( - (None, ('write_enabled', 'description', 'expires', 'allowed_ips')), + FieldSet('write_enabled', 'description', 'expires', 'allowed_ips'), ) nullable_fields = ( 'expires', 'description', 'allowed_ips', diff --git a/netbox/users/forms/filtersets.py b/netbox/users/forms/filtersets.py index 23bbe45e1..2d5644b98 100644 --- a/netbox/users/forms/filtersets.py +++ b/netbox/users/forms/filtersets.py @@ -7,6 +7,7 @@ from netbox.forms.mixins import SavedFiltersMixin from users.models import Group, ObjectPermission, Token, User from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES, FilterForm from utilities.forms.fields import DynamicModelMultipleChoiceField +from utilities.forms.rendering import FieldSet from utilities.forms.widgets import DateTimePicker __all__ = ( @@ -20,16 +21,16 @@ __all__ = ( class GroupFilterForm(NetBoxModelFilterSetForm): model = Group fieldsets = ( - (None, ('q', 'filter_id',)), + FieldSet('q', 'filter_id',), ) class UserFilterForm(NetBoxModelFilterSetForm): model = User fieldsets = ( - (None, ('q', 'filter_id',)), - (_('Group'), ('group_id',)), - (_('Status'), ('is_active', 'is_staff', 'is_superuser')), + FieldSet('q', 'filter_id',), + FieldSet('group_id', name=_('Group')), + FieldSet('is_active', 'is_staff', 'is_superuser', name=_('Status')), ) group_id = DynamicModelMultipleChoiceField( queryset=Group.objects.all(), @@ -62,9 +63,9 @@ class UserFilterForm(NetBoxModelFilterSetForm): class ObjectPermissionFilterForm(NetBoxModelFilterSetForm): model = ObjectPermission fieldsets = ( - (None, ('q', 'filter_id',)), - (_('Permission'), ('enabled', 'group_id', 'user_id')), - (_('Actions'), ('can_view', 'can_add', 'can_change', 'can_delete')), + FieldSet('q', 'filter_id',), + FieldSet('enabled', 'group_id', 'user_id', name=_('Permission')), + FieldSet('can_view', 'can_add', 'can_change', 'can_delete', name=_('Actions')), ) enabled = forms.NullBooleanField( label=_('Enabled'), @@ -116,8 +117,8 @@ class ObjectPermissionFilterForm(NetBoxModelFilterSetForm): class TokenFilterForm(SavedFiltersMixin, FilterForm): model = Token fieldsets = ( - (None, ('q', 'filter_id',)), - (_('Token'), ('user_id', 'write_enabled', 'expires', 'last_used')), + FieldSet('q', 'filter_id',), + FieldSet('user_id', 'write_enabled', 'expires', 'last_used', name=_('Token')), ) user_id = DynamicModelMultipleChoiceField( queryset=get_user_model().objects.all(), diff --git a/netbox/users/forms/model_forms.py b/netbox/users/forms/model_forms.py index 6c717d1ea..1f199d35c 100644 --- a/netbox/users/forms/model_forms.py +++ b/netbox/users/forms/model_forms.py @@ -13,6 +13,7 @@ from netbox.preferences import PREFERENCES from users.constants import * from users.models import * from utilities.forms.fields import ContentTypeMultipleChoiceField, DynamicModelMultipleChoiceField +from utilities.forms.rendering import FieldSet from utilities.forms.widgets import DateTimePicker from utilities.permissions import qs_filter_from_constraints from utilities.utils import flatten_dict @@ -53,15 +54,10 @@ class UserConfigFormMetaclass(forms.models.ModelFormMetaclass): class UserConfigForm(forms.ModelForm, metaclass=UserConfigFormMetaclass): fieldsets = ( - (_('User Interface'), ( - 'locale.language', - 'pagination.per_page', - 'pagination.placement', - 'ui.colormode', - )), - (_('Miscellaneous'), ( - 'data_format', - )), + FieldSet( + 'locale.language', 'pagination.per_page', 'pagination.placement', 'ui.colormode', name=_('User Interface') + ), + FieldSet('data_format', name=_('Miscellaneous')), ) # List of clearable preferences pk = forms.MultipleChoiceField( @@ -189,10 +185,10 @@ class UserForm(forms.ModelForm): ) fieldsets = ( - (_('User'), ('username', 'password', 'confirm_password', 'first_name', 'last_name', 'email')), - (_('Groups'), ('groups', )), - (_('Status'), ('is_active', 'is_staff', 'is_superuser')), - (_('Permissions'), ('object_permissions',)), + FieldSet('username', 'password', 'confirm_password', 'first_name', 'last_name', 'email', name=_('User')), + FieldSet('groups', name=_('Groups')), + FieldSet('is_active', 'is_staff', 'is_superuser', name=_('Status')), + FieldSet('object_permissions', name=_('Permissions')), ) class Meta: @@ -246,9 +242,9 @@ class GroupForm(forms.ModelForm): ) fieldsets = ( - (None, ('name', )), - (_('Users'), ('users', )), - (_('Permissions'), ('object_permissions', )), + FieldSet('name'), + FieldSet('users', name=_('Users')), + FieldSet('object_permissions', name=_('Permissions')), ) class Meta: @@ -312,11 +308,11 @@ class ObjectPermissionForm(forms.ModelForm): ) fieldsets = ( - (None, ('name', 'description', 'enabled',)), - (_('Actions'), ('can_view', 'can_add', 'can_change', 'can_delete', 'actions')), - (_('Objects'), ('object_types', )), - (_('Assignment'), ('groups', 'users')), - (_('Constraints'), ('constraints',)) + FieldSet('name', 'description', 'enabled'), + FieldSet('can_view', 'can_add', 'can_change', 'can_delete', 'actions', name=_('Actions')), + FieldSet('object_types', name=_('Objects')), + FieldSet('groups', 'users', name=_('Assignment')), + FieldSet('constraints', name=_('Constraints')) ) class Meta: diff --git a/netbox/utilities/forms/rendering.py b/netbox/utilities/forms/rendering.py index ea73c38ff..0d9344131 100644 --- a/netbox/utilities/forms/rendering.py +++ b/netbox/utilities/forms/rendering.py @@ -33,10 +33,11 @@ class TabbedGroups: """ Two or more groups of fields (FieldSets) arranged under tabs among which the user can navigate. """ - def __init__(self, *groups): - self.groups = [ - FieldSet(*group, name=name) for name, *group in groups - ] + def __init__(self, *fieldsets): + for fs in fieldsets: + if not fs.name: + raise ValueError(f"Grouped fieldset {fs} must have a name.") + self.groups = fieldsets # Initialize a random ID for the group (for tab selection) self.id = ''.join( diff --git a/netbox/utilities/templatetags/form_helpers.py b/netbox/utilities/templatetags/form_helpers.py index 48a1a5aa8..5365e1c80 100644 --- a/netbox/utilities/templatetags/form_helpers.py +++ b/netbox/utilities/templatetags/form_helpers.py @@ -1,3 +1,5 @@ +import warnings + from django import template from utilities.forms.rendering import FieldSet, InlineFields, ObjectAttribute, TabbedGroups @@ -52,8 +54,12 @@ def render_fieldset(form, fieldset): """ Render a group set of fields. """ + # TODO: Remove in NetBox v4.1 # Handle legacy tuple-based fieldset definitions, e.g. (_('Label'), ('field1, 'field2', 'field3')) if type(fieldset) is not FieldSet: + warnings.warn( + f"{form.__class__} fieldsets contains a non-FieldSet item: {fieldset}" + ) name, fields = fieldset fieldset = FieldSet(*fields, name=name) diff --git a/netbox/virtualization/forms/bulk_edit.py b/netbox/virtualization/forms/bulk_edit.py index eaf252824..2bd3434ac 100644 --- a/netbox/virtualization/forms/bulk_edit.py +++ b/netbox/virtualization/forms/bulk_edit.py @@ -10,6 +10,7 @@ from netbox.forms import NetBoxModelBulkEditForm from tenancy.models import Tenant from utilities.forms import BulkRenameForm, add_blank_choice from utilities.forms.fields import CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField +from utilities.forms.rendering import FieldSet from utilities.forms.widgets import BulkEditNullBooleanSelect from virtualization.choices import * from virtualization.models import * @@ -35,7 +36,7 @@ class ClusterTypeBulkEditForm(NetBoxModelBulkEditForm): model = ClusterType fieldsets = ( - (None, ('description',)), + FieldSet('description'), ) nullable_fields = ('description',) @@ -49,7 +50,7 @@ class ClusterGroupBulkEditForm(NetBoxModelBulkEditForm): model = ClusterGroup fieldsets = ( - (None, ('description',)), + FieldSet('description'), ) nullable_fields = ('description',) @@ -104,8 +105,8 @@ class ClusterBulkEditForm(NetBoxModelBulkEditForm): model = Cluster fieldsets = ( - (None, ('type', 'group', 'status', 'tenant', 'description')), - (_('Site'), ('region', 'site_group', 'site')), + FieldSet('type', 'group', 'status', 'tenant', 'description'), + FieldSet('region', 'site_group', 'site', name=_('Site')), ) nullable_fields = ( 'group', 'site', 'tenant', 'description', 'comments', @@ -185,9 +186,9 @@ class VirtualMachineBulkEditForm(NetBoxModelBulkEditForm): model = VirtualMachine fieldsets = ( - (None, ('site', 'cluster', 'device', 'status', 'role', 'tenant', 'platform', 'description')), - (_('Resources'), ('vcpus', 'memory', 'disk')), - ('Configuration', ('config_template',)), + FieldSet('site', 'cluster', 'device', 'status', 'role', 'tenant', 'platform', 'description'), + FieldSet('vcpus', 'memory', 'disk', name=_('Resources')), + FieldSet('config_template', name=_('Configuration')), ) nullable_fields = ( 'site', 'cluster', 'device', 'role', 'tenant', 'platform', 'vcpus', 'memory', 'disk', 'description', 'comments', @@ -262,9 +263,9 @@ class VMInterfaceBulkEditForm(NetBoxModelBulkEditForm): model = VMInterface fieldsets = ( - (None, ('mtu', 'enabled', 'vrf', 'description')), - (_('Related Interfaces'), ('parent', 'bridge')), - (_('802.1Q Switching'), ('mode', 'vlan_group', 'untagged_vlan', 'tagged_vlans')), + FieldSet('mtu', 'enabled', 'vrf', 'description'), + FieldSet('parent', 'bridge', name=_('Related Interfaces')), + FieldSet('mode', 'vlan_group', 'untagged_vlan', 'tagged_vlans', name=_('802.1Q Switching')), ) nullable_fields = ( 'parent', 'bridge', 'mtu', 'vrf', 'description', @@ -340,7 +341,7 @@ class VirtualDiskBulkEditForm(NetBoxModelBulkEditForm): model = VirtualDisk fieldsets = ( - (None, ('size', 'description')), + FieldSet('size', 'description'), ) nullable_fields = ('description',) diff --git a/netbox/virtualization/forms/filtersets.py b/netbox/virtualization/forms/filtersets.py index 5b0d097f8..1cb652a1b 100644 --- a/netbox/virtualization/forms/filtersets.py +++ b/netbox/virtualization/forms/filtersets.py @@ -9,6 +9,7 @@ from netbox.forms import NetBoxModelFilterSetForm from tenancy.forms import ContactModelFilterForm, TenancyFilterForm from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES from utilities.forms.fields import DynamicModelMultipleChoiceField, TagFilterField +from utilities.forms.rendering import FieldSet from virtualization.choices import * from virtualization.models import * from vpn.models import L2VPN @@ -32,19 +33,19 @@ class ClusterGroupFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm): model = ClusterGroup tag = TagFilterField(model) fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Contacts'), ('contact', 'contact_role', 'contact_group')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')), ) class ClusterFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFilterSetForm): model = Cluster fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Attributes'), ('group_id', 'type_id', 'status')), - (_('Location'), ('region_id', 'site_group_id', 'site_id')), - (_('Tenant'), ('tenant_group_id', 'tenant_id')), - (_('Contacts'), ('contact', 'contact_role', 'contact_group')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('group_id', 'type_id', 'status', name=_('Attributes')), + FieldSet('region_id', 'site_group_id', 'site_id', name=_('Location')), + FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), + FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')), ) selector_fields = ('filter_id', 'q', 'group_id') type_id = DynamicModelMultipleChoiceField( @@ -94,12 +95,15 @@ class VirtualMachineFilterForm( ): model = VirtualMachine fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Cluster'), ('cluster_group_id', 'cluster_type_id', 'cluster_id', 'device_id')), - (_('Location'), ('region_id', 'site_group_id', 'site_id')), - (_('Attributes'), ('status', 'role_id', 'platform_id', 'mac_address', 'has_primary_ip', 'config_template_id', 'local_context_data')), - (_('Tenant'), ('tenant_group_id', 'tenant_id')), - (_('Contacts'), ('contact', 'contact_role', 'contact_group')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('cluster_group_id', 'cluster_type_id', 'cluster_id', 'device_id', name=_('Cluster')), + FieldSet('region_id', 'site_group_id', 'site_id', name=_('Location')), + FieldSet( + 'status', 'role_id', 'platform_id', 'mac_address', 'has_primary_ip', 'config_template_id', + 'local_context_data', name=_('Attributes') + ), + FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), + FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')), ) cluster_group_id = DynamicModelMultipleChoiceField( queryset=ClusterGroup.objects.all(), @@ -185,9 +189,9 @@ class VirtualMachineFilterForm( class VMInterfaceFilterForm(NetBoxModelFilterSetForm): model = VMInterface fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Virtual Machine'), ('cluster_id', 'virtual_machine_id')), - (_('Attributes'), ('enabled', 'mac_address', 'vrf_id', 'l2vpn_id')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('cluster_id', 'virtual_machine_id', name=_('Virtual Machine')), + FieldSet('enabled', 'mac_address', 'vrf_id', 'l2vpn_id', name=_('Attributes')), ) selector_fields = ('filter_id', 'q', 'virtual_machine_id') cluster_id = DynamicModelMultipleChoiceField( @@ -230,9 +234,9 @@ class VMInterfaceFilterForm(NetBoxModelFilterSetForm): class VirtualDiskFilterForm(NetBoxModelFilterSetForm): model = VirtualDisk fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Virtual Machine'), ('virtual_machine_id',)), - (_('Attributes'), ('size',)), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('virtual_machine_id', name=_('Virtual Machine')), + FieldSet('size', name=_('Attributes')), ) virtual_machine_id = DynamicModelMultipleChoiceField( queryset=VirtualMachine.objects.all(), diff --git a/netbox/virtualization/forms/model_forms.py b/netbox/virtualization/forms/model_forms.py index 186ab8182..bfdfc9ada 100644 --- a/netbox/virtualization/forms/model_forms.py +++ b/netbox/virtualization/forms/model_forms.py @@ -13,6 +13,7 @@ from utilities.forms import ConfirmationForm from utilities.forms.fields import ( CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, JSONField, SlugField, ) +from utilities.forms.rendering import FieldSet from utilities.forms.widgets import HTMXSelect from virtualization.models import * @@ -32,9 +33,7 @@ class ClusterTypeForm(NetBoxModelForm): slug = SlugField() fieldsets = ( - (_('Cluster Type'), ( - 'name', 'slug', 'description', 'tags', - )), + FieldSet('name', 'slug', 'description', 'tags', name=_('Cluster Type')), ) class Meta: @@ -48,9 +47,7 @@ class ClusterGroupForm(NetBoxModelForm): slug = SlugField() fieldsets = ( - (_('Cluster Group'), ( - 'name', 'slug', 'description', 'tags', - )), + FieldSet('name', 'slug', 'description', 'tags', name=_('Cluster Group')), ) class Meta: @@ -79,8 +76,8 @@ class ClusterForm(TenancyForm, NetBoxModelForm): comments = CommentField() fieldsets = ( - (_('Cluster'), ('name', 'type', 'group', 'site', 'status', 'description', 'tags')), - (_('Tenancy'), ('tenant_group', 'tenant')), + FieldSet('name', 'type', 'group', 'site', 'status', 'description', 'tags', name=_('Cluster')), + FieldSet('tenant_group', 'tenant', name=_('Tenancy')), ) class Meta: @@ -220,12 +217,12 @@ class VirtualMachineForm(TenancyForm, NetBoxModelForm): comments = CommentField() fieldsets = ( - (_('Virtual Machine'), ('name', 'role', 'status', 'description', 'tags')), - (_('Site/Cluster'), ('site', 'cluster', 'device')), - (_('Tenancy'), ('tenant_group', 'tenant')), - (_('Management'), ('platform', 'primary_ip4', 'primary_ip6', 'config_template')), - (_('Resources'), ('vcpus', 'memory', 'disk')), - (_('Config Context'), ('local_context_data',)), + FieldSet('name', 'role', 'status', 'description', 'tags', name=_('Virtual Machine')), + FieldSet('site', 'cluster', 'device', name=_('Site/Cluster')), + FieldSet('tenant_group', 'tenant', name=_('Tenancy')), + FieldSet('platform', 'primary_ip4', 'primary_ip6', 'config_template', name=_('Management')), + FieldSet('vcpus', 'memory', 'disk', name=_('Resources')), + FieldSet('local_context_data', name=_('Config Context')), ) class Meta: @@ -348,11 +345,11 @@ class VMInterfaceForm(InterfaceCommonForm, VMComponentForm): ) fieldsets = ( - (_('Interface'), ('virtual_machine', 'name', 'description', 'tags')), - (_('Addressing'), ('vrf', 'mac_address')), - (_('Operation'), ('mtu', 'enabled')), - (_('Related Interfaces'), ('parent', 'bridge')), - (_('802.1Q Switching'), ('mode', 'vlan_group', 'untagged_vlan', 'tagged_vlans')), + FieldSet('virtual_machine', 'name', 'description', 'tags', name=_('Interface')), + FieldSet('vrf', 'mac_address', name=_('Addressing')), + FieldSet('mtu', 'enabled', name=_('Operation')), + FieldSet('parent', 'bridge', name=_('Related Interfaces')), + FieldSet('mode', 'vlan_group', 'untagged_vlan', 'tagged_vlans', name=_('802.1Q Switching')), ) class Meta: @@ -372,7 +369,7 @@ class VMInterfaceForm(InterfaceCommonForm, VMComponentForm): class VirtualDiskForm(VMComponentForm): fieldsets = ( - (_('Disk'), ('virtual_machine', 'name', 'size', 'description', 'tags')), + FieldSet('virtual_machine', 'name', 'size', 'description', 'tags', name=_('Disk')), ) class Meta: diff --git a/netbox/vpn/forms/bulk_edit.py b/netbox/vpn/forms/bulk_edit.py index c3e8eb3ca..a7595a2a7 100644 --- a/netbox/vpn/forms/bulk_edit.py +++ b/netbox/vpn/forms/bulk_edit.py @@ -5,6 +5,7 @@ from netbox.forms import NetBoxModelBulkEditForm from tenancy.models import Tenant from utilities.forms import add_blank_choice from utilities.forms.fields import CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField +from utilities.forms.rendering import FieldSet from vpn.choices import * from vpn.models import * @@ -72,9 +73,9 @@ class TunnelBulkEditForm(NetBoxModelBulkEditForm): model = Tunnel fieldsets = ( - (_('Tunnel'), ('status', 'group', 'encapsulation', 'tunnel_id', 'description')), - (_('Security'), ('ipsec_profile',)), - (_('Tenancy'), ('tenant',)), + FieldSet('status', 'group', 'encapsulation', 'tunnel_id', 'description', name=_('Tunnel')), + FieldSet('ipsec_profile', name=_('Security')), + FieldSet('tenant', name=_('Tenancy')), ) nullable_fields = ( 'group', 'ipsec_profile', 'tunnel_id', 'tenant', 'description', 'comments', @@ -125,10 +126,10 @@ class IKEProposalBulkEditForm(NetBoxModelBulkEditForm): model = IKEProposal fieldsets = ( - (None, ( + FieldSet( 'authentication_method', 'encryption_algorithm', 'authentication_algorithm', 'group', 'sa_lifetime', 'description', - )), + ), ) nullable_fields = ( 'sa_lifetime', 'description', 'comments', @@ -159,9 +160,7 @@ class IKEPolicyBulkEditForm(NetBoxModelBulkEditForm): model = IKEPolicy fieldsets = ( - (None, ( - 'version', 'mode', 'preshared_key', 'description', - )), + FieldSet('version', 'mode', 'preshared_key', 'description'), ) nullable_fields = ( 'mode', 'preshared_key', 'description', 'comments', @@ -196,10 +195,10 @@ class IPSecProposalBulkEditForm(NetBoxModelBulkEditForm): model = IPSecProposal fieldsets = ( - (None, ( + FieldSet( 'encryption_algorithm', 'authentication_algorithm', 'sa_lifetime_seconds', 'sa_lifetime_data', 'description', - )), + ), ) nullable_fields = ( 'sa_lifetime_seconds', 'sa_lifetime_data', 'description', 'comments', @@ -221,7 +220,7 @@ class IPSecPolicyBulkEditForm(NetBoxModelBulkEditForm): model = IPSecPolicy fieldsets = ( - (None, ('pfs_group', 'description',)), + FieldSet('pfs_group', 'description'), ) nullable_fields = ( 'pfs_group', 'description', 'comments', @@ -253,9 +252,7 @@ class IPSecProfileBulkEditForm(NetBoxModelBulkEditForm): model = IPSecProfile fieldsets = ( - (_('Profile'), ( - 'mode', 'ike_policy', 'ipsec_policy', 'description', - )), + FieldSet('mode', 'ike_policy', 'ipsec_policy', 'description', name=_('Profile')), ) nullable_fields = ( 'description', 'comments', @@ -282,7 +279,7 @@ class L2VPNBulkEditForm(NetBoxModelBulkEditForm): model = L2VPN fieldsets = ( - (None, ('type', 'tenant', 'description')), + FieldSet('type', 'tenant', 'description'), ) nullable_fields = ('tenant', 'description', 'comments') diff --git a/netbox/vpn/forms/filtersets.py b/netbox/vpn/forms/filtersets.py index a9326c4bc..d25719d06 100644 --- a/netbox/vpn/forms/filtersets.py +++ b/netbox/vpn/forms/filtersets.py @@ -9,6 +9,7 @@ from tenancy.forms import TenancyFilterForm from utilities.forms.fields import ( ContentTypeMultipleChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, TagFilterField, ) +from utilities.forms.rendering import FieldSet from utilities.forms.utils import add_blank_choice from virtualization.models import VirtualMachine from vpn.choices import * @@ -37,10 +38,10 @@ class TunnelGroupFilterForm(NetBoxModelFilterSetForm): class TunnelFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = Tunnel fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Tunnel'), ('status', 'encapsulation', 'tunnel_id')), - (_('Security'), ('ipsec_profile_id',)), - (_('Tenancy'), ('tenant_group_id', 'tenant_id')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('status', 'encapsulation', 'tunnel_id', name=_('Tunnel')), + FieldSet('ipsec_profile_id', name=_('Security')), + FieldSet('tenant_group_id', 'tenant_id', name=_('Tenancy')), ) status = forms.MultipleChoiceField( label=_('Status'), @@ -72,8 +73,8 @@ class TunnelFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): class TunnelTerminationFilterForm(NetBoxModelFilterSetForm): model = TunnelTermination fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Termination'), ('tunnel_id', 'role')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('tunnel_id', 'role', name=_('Termination')), ) tunnel_id = DynamicModelMultipleChoiceField( queryset=Tunnel.objects.all(), @@ -91,8 +92,10 @@ class TunnelTerminationFilterForm(NetBoxModelFilterSetForm): class IKEProposalFilterForm(NetBoxModelFilterSetForm): model = IKEProposal fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Parameters'), ('authentication_method', 'encryption_algorithm', 'authentication_algorithm', 'group')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet( + 'authentication_method', 'encryption_algorithm', 'authentication_algorithm', 'group', name=_('Parameters') + ), ) authentication_method = forms.MultipleChoiceField( label=_('Authentication method'), @@ -120,8 +123,8 @@ class IKEProposalFilterForm(NetBoxModelFilterSetForm): class IKEPolicyFilterForm(NetBoxModelFilterSetForm): model = IKEPolicy fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Parameters'), ('version', 'mode', 'proposal_id')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('version', 'mode', 'proposal_id', name=_('Parameters')), ) version = forms.MultipleChoiceField( label=_('IKE version'), @@ -144,8 +147,8 @@ class IKEPolicyFilterForm(NetBoxModelFilterSetForm): class IPSecProposalFilterForm(NetBoxModelFilterSetForm): model = IPSecProposal fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Parameters'), ('encryption_algorithm', 'authentication_algorithm')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('encryption_algorithm', 'authentication_algorithm', name=_('Parameters')), ) encryption_algorithm = forms.MultipleChoiceField( label=_('Encryption algorithm'), @@ -163,8 +166,8 @@ class IPSecProposalFilterForm(NetBoxModelFilterSetForm): class IPSecPolicyFilterForm(NetBoxModelFilterSetForm): model = IPSecPolicy fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Parameters'), ('proposal_id', 'pfs_group')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('proposal_id', 'pfs_group', name=_('Parameters')), ) proposal_id = DynamicModelMultipleChoiceField( queryset=IKEProposal.objects.all(), @@ -182,8 +185,8 @@ class IPSecPolicyFilterForm(NetBoxModelFilterSetForm): class IPSecProfileFilterForm(NetBoxModelFilterSetForm): model = IPSecProfile fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Profile'), ('mode', 'ike_policy_id', 'ipsec_policy_id')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('mode', 'ike_policy_id', 'ipsec_policy_id', name=_('Profile')), ) mode = forms.MultipleChoiceField( label=_('Mode'), @@ -206,9 +209,9 @@ class IPSecProfileFilterForm(NetBoxModelFilterSetForm): class L2VPNFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = L2VPN fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Attributes'), ('type', 'import_target_id', 'export_target_id')), - (_('Tenant'), ('tenant_group_id', 'tenant_id')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('type', 'import_target_id', 'export_target_id', name=_('Attributes')), + FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), ) type = forms.ChoiceField( label=_('Type'), @@ -231,10 +234,11 @@ class L2VPNFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): class L2VPNTerminationFilterForm(NetBoxModelFilterSetForm): model = L2VPNTermination fieldsets = ( - (None, ('filter_id', 'l2vpn_id',)), - (_('Assigned Object'), ( + FieldSet('filter_id', 'l2vpn_id',), + FieldSet( 'assigned_object_type_id', 'region_id', 'site_id', 'device_id', 'virtual_machine_id', 'vlan_id', - )), + name=_('Assigned Object') + ), ) l2vpn_id = DynamicModelChoiceField( queryset=L2VPN.objects.all(), diff --git a/netbox/vpn/forms/model_forms.py b/netbox/vpn/forms/model_forms.py index 9674ee2f9..eb2f839d5 100644 --- a/netbox/vpn/forms/model_forms.py +++ b/netbox/vpn/forms/model_forms.py @@ -7,7 +7,7 @@ from ipam.models import IPAddress, RouteTarget, VLAN from netbox.forms import NetBoxModelForm from tenancy.forms import TenancyForm from utilities.forms.fields import CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, SlugField -from utilities.forms.rendering import TabbedGroups +from utilities.forms.rendering import FieldSet, TabbedGroups from utilities.forms.utils import add_blank_choice, get_field_value from utilities.forms.widgets import HTMXSelect from virtualization.models import VirtualMachine, VMInterface @@ -33,7 +33,7 @@ class TunnelGroupForm(NetBoxModelForm): slug = SlugField() fieldsets = ( - (_('Tunnel Group'), ('name', 'slug', 'description', 'tags')), + FieldSet('name', 'slug', 'description', 'tags', name=_('Tunnel Group')), ) class Meta: @@ -57,9 +57,9 @@ class TunnelForm(TenancyForm, NetBoxModelForm): comments = CommentField() fieldsets = ( - (_('Tunnel'), ('name', 'status', 'group', 'encapsulation', 'description', 'tunnel_id', 'tags')), - (_('Security'), ('ipsec_profile',)), - (_('Tenancy'), ('tenant_group', 'tenant')), + FieldSet('name', 'status', 'group', 'encapsulation', 'description', 'tunnel_id', 'tags', name=_('Tunnel')), + FieldSet('ipsec_profile', name=_('Security')), + FieldSet('tenant_group', 'tenant', name=_('Tenancy')), ) class Meta: @@ -142,17 +142,15 @@ class TunnelCreateForm(TunnelForm): ) fieldsets = ( - (_('Tunnel'), ('name', 'status', 'group', 'encapsulation', 'description', 'tunnel_id', 'tags')), - (_('Security'), ('ipsec_profile',)), - (_('Tenancy'), ('tenant_group', 'tenant')), - (_('First Termination'), ( + FieldSet('name', 'status', 'group', 'encapsulation', 'description', 'tunnel_id', 'tags', name=_('Tunnel')), + FieldSet('ipsec_profile', name=_('Security')), + FieldSet('tenant_group', 'tenant', name=_('Tenancy')), + FieldSet( 'termination1_role', 'termination1_type', 'termination1_parent', 'termination1_termination', - 'termination1_outside_ip', - )), - (_('Second Termination'), ( + 'termination1_outside_ip', name=_('First Termination')), + FieldSet( 'termination2_role', 'termination2_type', 'termination2_parent', 'termination2_termination', - 'termination2_outside_ip', - )), + 'termination2_outside_ip', name=_('Second Termination')), ) def __init__(self, *args, initial=None, **kwargs): @@ -254,7 +252,7 @@ class TunnelTerminationForm(NetBoxModelForm): ) fieldsets = ( - (None, ('tunnel', 'role', 'type', 'parent', 'termination', 'outside_ip', 'tags')), + FieldSet('tunnel', 'role', 'type', 'parent', 'termination', 'outside_ip', 'tags'), ) class Meta: @@ -297,10 +295,11 @@ class TunnelTerminationForm(NetBoxModelForm): class IKEProposalForm(NetBoxModelForm): fieldsets = ( - (_('Proposal'), ('name', 'description', 'tags')), - (_('Parameters'), ( + FieldSet('name', 'description', 'tags', name=_('Proposal')), + FieldSet( 'authentication_method', 'encryption_algorithm', 'authentication_algorithm', 'group', 'sa_lifetime', - )), + name=_('Parameters') + ), ) class Meta: @@ -318,8 +317,8 @@ class IKEPolicyForm(NetBoxModelForm): ) fieldsets = ( - (_('Policy'), ('name', 'description', 'tags')), - (_('Parameters'), ('version', 'mode', 'proposals', 'preshared_key')), + FieldSet('name', 'description', 'tags', name=_('Policy')), + FieldSet('version', 'mode', 'proposals', 'preshared_key', name=_('Parameters')), ) class Meta: @@ -332,10 +331,11 @@ class IKEPolicyForm(NetBoxModelForm): class IPSecProposalForm(NetBoxModelForm): fieldsets = ( - (_('Proposal'), ('name', 'description', 'tags')), - (_('Parameters'), ( + FieldSet('name', 'description', 'tags', name=_('Proposal')), + FieldSet( 'encryption_algorithm', 'authentication_algorithm', 'sa_lifetime_seconds', 'sa_lifetime_data', - )), + name=_('Parameters') + ), ) class Meta: @@ -353,8 +353,8 @@ class IPSecPolicyForm(NetBoxModelForm): ) fieldsets = ( - (_('Policy'), ('name', 'description', 'tags')), - (_('Parameters'), ('proposals', 'pfs_group')), + FieldSet('name', 'description', 'tags', name=_('Policy')), + FieldSet('proposals', 'pfs_group', name=_('Parameters')), ) class Meta: @@ -376,8 +376,8 @@ class IPSecProfileForm(NetBoxModelForm): comments = CommentField() fieldsets = ( - (_('Profile'), ('name', 'description', 'tags')), - (_('Parameters'), ('mode', 'ike_policy', 'ipsec_policy')), + FieldSet('name', 'description', 'tags', name=_('Profile')), + FieldSet('mode', 'ike_policy', 'ipsec_policy', name=_('Parameters')), ) class Meta: @@ -406,9 +406,9 @@ class L2VPNForm(TenancyForm, NetBoxModelForm): comments = CommentField() fieldsets = ( - (_('L2VPN'), ('name', 'slug', 'type', 'identifier', 'description', 'tags')), - (_('Route Targets'), ('import_targets', 'export_targets')), - (_('Tenancy'), ('tenant_group', 'tenant')), + FieldSet('name', 'slug', 'type', 'identifier', 'description', 'tags', name=_('L2VPN')), + FieldSet('import_targets', 'export_targets', name=_('Route Targets')), + FieldSet('tenant_group', 'tenant', name=_('Tenancy')), ) class Meta: @@ -446,15 +446,15 @@ class L2VPNTerminationForm(NetBoxModelForm): ) fieldsets = ( - (None, ( + FieldSet( 'l2vpn', TabbedGroups( - (_('VLAN'), 'vlan'), - (_('Device'), 'interface'), - (_('Virtual Machine'), 'vminterface'), + FieldSet('vlan', name=_('VLAN')), + FieldSet('interface', name=_('Device')), + FieldSet('vminterface', name=_('Virtual Machine')), ), 'tags', - )), + ), ) class Meta: diff --git a/netbox/wireless/forms/bulk_edit.py b/netbox/wireless/forms/bulk_edit.py index 43e804345..84916e8d9 100644 --- a/netbox/wireless/forms/bulk_edit.py +++ b/netbox/wireless/forms/bulk_edit.py @@ -7,6 +7,7 @@ from netbox.forms import NetBoxModelBulkEditForm from tenancy.models import Tenant from utilities.forms import add_blank_choice from utilities.forms.fields import CommentField, DynamicModelChoiceField +from utilities.forms.rendering import FieldSet from wireless.choices import * from wireless.constants import SSID_MAX_LENGTH from wireless.models import * @@ -32,7 +33,7 @@ class WirelessLANGroupBulkEditForm(NetBoxModelBulkEditForm): model = WirelessLANGroup fieldsets = ( - (None, ('parent', 'description')), + FieldSet('parent', 'description'), ) nullable_fields = ('parent', 'description') @@ -86,8 +87,8 @@ class WirelessLANBulkEditForm(NetBoxModelBulkEditForm): model = WirelessLAN fieldsets = ( - (None, ('group', 'ssid', 'status', 'vlan', 'tenant', 'description')), - (_('Authentication'), ('auth_type', 'auth_cipher', 'auth_psk')), + FieldSet('group', 'ssid', 'status', 'vlan', 'tenant', 'description'), + FieldSet('auth_type', 'auth_cipher', 'auth_psk', name=_('Authentication')), ) nullable_fields = ( 'ssid', 'group', 'vlan', 'tenant', 'description', 'auth_type', 'auth_cipher', 'auth_psk', 'comments', @@ -133,8 +134,8 @@ class WirelessLinkBulkEditForm(NetBoxModelBulkEditForm): model = WirelessLink fieldsets = ( - (None, ('ssid', 'status', 'tenant', 'description')), - (_('Authentication'), ('auth_type', 'auth_cipher', 'auth_psk')) + FieldSet('ssid', 'status', 'tenant', 'description'), + FieldSet('auth_type', 'auth_cipher', 'auth_psk', name=_('Authentication')) ) nullable_fields = ( 'ssid', 'tenant', 'description', 'auth_type', 'auth_cipher', 'auth_psk', 'comments', diff --git a/netbox/wireless/forms/filtersets.py b/netbox/wireless/forms/filtersets.py index f4c1cb523..2458d7b48 100644 --- a/netbox/wireless/forms/filtersets.py +++ b/netbox/wireless/forms/filtersets.py @@ -6,6 +6,7 @@ from netbox.forms import NetBoxModelFilterSetForm from tenancy.forms import TenancyFilterForm from utilities.forms import add_blank_choice from utilities.forms.fields import DynamicModelMultipleChoiceField, TagFilterField +from utilities.forms.rendering import FieldSet from wireless.choices import * from wireless.models import * @@ -29,10 +30,10 @@ class WirelessLANGroupFilterForm(NetBoxModelFilterSetForm): class WirelessLANFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = WirelessLAN fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Attributes'), ('ssid', 'group_id', 'status')), - (_('Tenant'), ('tenant_group_id', 'tenant_id')), - (_('Authentication'), ('auth_type', 'auth_cipher', 'auth_psk')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('ssid', 'group_id', 'status', name=_('Attributes')), + FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), + FieldSet('auth_type', 'auth_cipher', 'auth_psk', name=_('Authentication')), ) ssid = forms.CharField( required=False, @@ -69,10 +70,10 @@ class WirelessLANFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): class WirelessLinkFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = WirelessLink fieldsets = ( - (None, ('q', 'filter_id', 'tag')), - (_('Attributes'), ('ssid', 'status',)), - (_('Tenant'), ('tenant_group_id', 'tenant_id')), - (_('Authentication'), ('auth_type', 'auth_cipher', 'auth_psk')), + FieldSet('q', 'filter_id', 'tag'), + FieldSet('ssid', 'status', name=_('Attributes')), + FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), + FieldSet('auth_type', 'auth_cipher', 'auth_psk', name=_('Authentication')), ) ssid = forms.CharField( required=False, diff --git a/netbox/wireless/forms/model_forms.py b/netbox/wireless/forms/model_forms.py index 04e6fce83..05debf8bf 100644 --- a/netbox/wireless/forms/model_forms.py +++ b/netbox/wireless/forms/model_forms.py @@ -6,6 +6,7 @@ from ipam.models import VLAN from netbox.forms import NetBoxModelForm from tenancy.forms import TenancyForm from utilities.forms.fields import CommentField, DynamicModelChoiceField, SlugField +from utilities.forms.rendering import FieldSet from wireless.models import * __all__ = ( @@ -24,9 +25,7 @@ class WirelessLANGroupForm(NetBoxModelForm): slug = SlugField() fieldsets = ( - (_('Wireless LAN Group'), ( - 'parent', 'name', 'slug', 'description', 'tags', - )), + FieldSet('parent', 'name', 'slug', 'description', 'tags', name=_('Wireless LAN Group')), ) class Meta: @@ -51,9 +50,9 @@ class WirelessLANForm(TenancyForm, NetBoxModelForm): comments = CommentField() fieldsets = ( - (_('Wireless LAN'), ('ssid', 'group', 'vlan', 'status', 'description', 'tags')), - (_('Tenancy'), ('tenant_group', 'tenant')), - (_('Authentication'), ('auth_type', 'auth_cipher', 'auth_psk')), + FieldSet('ssid', 'group', 'vlan', 'status', 'description', 'tags', name=_('Wireless LAN')), + FieldSet('tenant_group', 'tenant', name=_('Tenancy')), + FieldSet('auth_type', 'auth_cipher', 'auth_psk', name=_('Authentication')), ) class Meta: @@ -158,11 +157,11 @@ class WirelessLinkForm(TenancyForm, NetBoxModelForm): comments = CommentField() fieldsets = ( - (_('Side A'), ('site_a', 'location_a', 'device_a', 'interface_a')), - (_('Side B'), ('site_b', 'location_b', 'device_b', 'interface_b')), - (_('Link'), ('status', 'ssid', 'description', 'tags')), - (_('Tenancy'), ('tenant_group', 'tenant')), - (_('Authentication'), ('auth_type', 'auth_cipher', 'auth_psk')), + FieldSet('site_a', 'location_a', 'device_a', 'interface_a', name=_('Side A')), + FieldSet('site_b', 'location_b', 'device_b', 'interface_b', name=_('Side B')), + FieldSet('status', 'ssid', 'description', 'tags', name=_('Link')), + FieldSet('tenant_group', 'tenant', name=_('Tenancy')), + FieldSet('auth_type', 'auth_cipher', 'auth_psk', name=_('Authentication')), ) class Meta: