From 4dda9686873ce4ad471f4481e21c3e5564fd5806 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 21 Oct 2025 16:59:53 -0400 Subject: [PATCH] Update forms for device & VM components --- netbox/dcim/forms/bulk_edit.py | 4 +- netbox/dcim/forms/bulk_import.py | 43 ++++++++++++---------- netbox/dcim/forms/filtersets.py | 3 +- netbox/dcim/forms/model_forms.py | 4 +- netbox/virtualization/forms/bulk_edit.py | 5 ++- netbox/virtualization/forms/bulk_import.py | 12 +++--- netbox/virtualization/forms/filtersets.py | 5 ++- netbox/virtualization/forms/model_forms.py | 3 +- 8 files changed, 44 insertions(+), 35 deletions(-) diff --git a/netbox/dcim/forms/bulk_edit.py b/netbox/dcim/forms/bulk_edit.py index cfc614073..eb3659fc2 100644 --- a/netbox/dcim/forms/bulk_edit.py +++ b/netbox/dcim/forms/bulk_edit.py @@ -13,7 +13,7 @@ from netbox.choices import * from netbox.forms import ( NestedGroupModelBulkEditForm, NetBoxModelBulkEditForm, OrganizationalModelBulkEditForm, PrimaryModelBulkEditForm, ) -from netbox.forms.mixins import ChangelogMessageMixin +from netbox.forms.mixins import ChangelogMessageMixin, OwnerMixin from tenancy.models import Tenant from users.models import User from utilities.forms import BulkEditForm, add_blank_choice, form_from_model @@ -1246,7 +1246,7 @@ class InventoryItemTemplateBulkEditForm(ComponentTemplateBulkEditForm): # Device components # -class ComponentBulkEditForm(NetBoxModelBulkEditForm): +class ComponentBulkEditForm(OwnerMixin, NetBoxModelBulkEditForm): device = forms.ModelChoiceField( label=_('Device'), queryset=Device.objects.all(), diff --git a/netbox/dcim/forms/bulk_import.py b/netbox/dcim/forms/bulk_import.py index 65abd9502..726c25518 100644 --- a/netbox/dcim/forms/bulk_import.py +++ b/netbox/dcim/forms/bulk_import.py @@ -12,7 +12,7 @@ from extras.models import ConfigTemplate from ipam.models import VRF, IPAddress from netbox.choices import * from netbox.forms import ( - NestedGroupModelBulkImportForm, NetBoxModelImportForm, OrganizationalModelBulkImportForm, + NestedGroupModelBulkImportForm, NetBoxModelImportForm, OrganizationalModelBulkImportForm, OwnerCSVMixin, PrimaryModelBulkImportForm, ) from tenancy.models import Tenant @@ -779,7 +779,7 @@ class ModuleImportForm(ModuleCommonForm, PrimaryModelBulkImportForm): # Device components # -class ConsolePortImportForm(NetBoxModelImportForm): +class ConsolePortImportForm(OwnerCSVMixin, NetBoxModelImportForm): device = CSVModelChoiceField( label=_('Device'), queryset=Device.objects.all(), @@ -802,10 +802,10 @@ class ConsolePortImportForm(NetBoxModelImportForm): class Meta: model = ConsolePort - fields = ('device', 'name', 'label', 'type', 'speed', 'mark_connected', 'description', 'tags') + fields = ('device', 'name', 'label', 'type', 'speed', 'mark_connected', 'description', 'owner', 'tags') -class ConsoleServerPortImportForm(NetBoxModelImportForm): +class ConsoleServerPortImportForm(OwnerCSVMixin, NetBoxModelImportForm): device = CSVModelChoiceField( label=_('Device'), queryset=Device.objects.all(), @@ -828,10 +828,10 @@ class ConsoleServerPortImportForm(NetBoxModelImportForm): class Meta: model = ConsoleServerPort - fields = ('device', 'name', 'label', 'type', 'speed', 'mark_connected', 'description', 'tags') + fields = ('device', 'name', 'label', 'type', 'speed', 'mark_connected', 'description', 'owner', 'tags') -class PowerPortImportForm(NetBoxModelImportForm): +class PowerPortImportForm(OwnerCSVMixin, NetBoxModelImportForm): device = CSVModelChoiceField( label=_('Device'), queryset=Device.objects.all(), @@ -847,11 +847,12 @@ class PowerPortImportForm(NetBoxModelImportForm): class Meta: model = PowerPort fields = ( - 'device', 'name', 'label', 'type', 'mark_connected', 'maximum_draw', 'allocated_draw', 'description', 'tags' + 'device', 'name', 'label', 'type', 'mark_connected', 'maximum_draw', 'allocated_draw', 'description', + 'owner', 'tags', ) -class PowerOutletImportForm(NetBoxModelImportForm): +class PowerOutletImportForm(OwnerCSVMixin, NetBoxModelImportForm): device = CSVModelChoiceField( label=_('Device'), queryset=Device.objects.all(), @@ -881,7 +882,7 @@ class PowerOutletImportForm(NetBoxModelImportForm): model = PowerOutlet fields = ( 'device', 'name', 'label', 'type', 'color', 'mark_connected', 'power_port', 'feed_leg', 'description', - 'tags', + 'owner', 'tags', ) def __init__(self, *args, **kwargs): @@ -907,7 +908,7 @@ class PowerOutletImportForm(NetBoxModelImportForm): self.fields['power_port'].queryset = PowerPort.objects.none() -class InterfaceImportForm(NetBoxModelImportForm): +class InterfaceImportForm(OwnerCSVMixin, NetBoxModelImportForm): device = CSVModelChoiceField( label=_('Device'), queryset=Device.objects.all(), @@ -990,7 +991,7 @@ class InterfaceImportForm(NetBoxModelImportForm): fields = ( 'device', 'name', 'label', 'parent', 'bridge', 'lag', 'type', 'speed', 'duplex', 'enabled', 'mark_connected', 'wwn', 'vdcs', 'mtu', 'mgmt_only', 'description', 'poe_mode', 'poe_type', 'mode', - 'vrf', 'rf_role', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width', 'tx_power', 'tags' + 'vrf', 'rf_role', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width', 'tx_power', 'owner', 'tags' ) def __init__(self, data=None, *args, **kwargs): @@ -1025,7 +1026,7 @@ class InterfaceImportForm(NetBoxModelImportForm): return self.cleaned_data['vdcs'] -class FrontPortImportForm(NetBoxModelImportForm): +class FrontPortImportForm(OwnerCSVMixin, NetBoxModelImportForm): device = CSVModelChoiceField( label=_('Device'), queryset=Device.objects.all(), @@ -1047,7 +1048,7 @@ class FrontPortImportForm(NetBoxModelImportForm): model = FrontPort fields = ( 'device', 'name', 'label', 'type', 'color', 'mark_connected', 'rear_port', 'rear_port_position', - 'description', 'tags' + 'description', 'owner', 'tags' ) def __init__(self, *args, **kwargs): @@ -1073,7 +1074,7 @@ class FrontPortImportForm(NetBoxModelImportForm): self.fields['rear_port'].queryset = RearPort.objects.none() -class RearPortImportForm(NetBoxModelImportForm): +class RearPortImportForm(OwnerCSVMixin, NetBoxModelImportForm): device = CSVModelChoiceField( label=_('Device'), queryset=Device.objects.all(), @@ -1087,10 +1088,12 @@ class RearPortImportForm(NetBoxModelImportForm): class Meta: model = RearPort - fields = ('device', 'name', 'label', 'type', 'color', 'mark_connected', 'positions', 'description', 'tags') + fields = ( + 'device', 'name', 'label', 'type', 'color', 'mark_connected', 'positions', 'description', 'owner', 'tags', + ) -class ModuleBayImportForm(NetBoxModelImportForm): +class ModuleBayImportForm(OwnerCSVMixin, NetBoxModelImportForm): device = CSVModelChoiceField( label=_('Device'), queryset=Device.objects.all(), @@ -1099,10 +1102,10 @@ class ModuleBayImportForm(NetBoxModelImportForm): class Meta: model = ModuleBay - fields = ('device', 'name', 'label', 'position', 'description', 'tags') + fields = ('device', 'name', 'label', 'position', 'description', 'owner', 'tags') -class DeviceBayImportForm(NetBoxModelImportForm): +class DeviceBayImportForm(OwnerCSVMixin, NetBoxModelImportForm): device = CSVModelChoiceField( label=_('Device'), queryset=Device.objects.all(), @@ -1121,7 +1124,7 @@ class DeviceBayImportForm(NetBoxModelImportForm): class Meta: model = DeviceBay - fields = ('device', 'name', 'label', 'installed_device', 'description', 'tags') + fields = ('device', 'name', 'label', 'installed_device', 'description', 'owner', 'tags') def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -1150,7 +1153,7 @@ class DeviceBayImportForm(NetBoxModelImportForm): self.fields['installed_device'].queryset = Device.objects.none() -class InventoryItemImportForm(OrganizationalModelBulkImportForm): +class InventoryItemImportForm(OwnerCSVMixin, NetBoxModelImportForm): device = CSVModelChoiceField( label=_('Device'), queryset=Device.objects.all(), diff --git a/netbox/dcim/forms/filtersets.py b/netbox/dcim/forms/filtersets.py index 50dff23b4..4d37460fd 100644 --- a/netbox/dcim/forms/filtersets.py +++ b/netbox/dcim/forms/filtersets.py @@ -12,6 +12,7 @@ from netbox.forms import ( NestedGroupModelFilterSetForm, NetBoxModelFilterSetForm, OrganizationalModelFilterSetForm, PrimaryModelFilterSetForm, ) +from netbox.forms.mixins import OwnerMixin from tenancy.forms import ContactModelFilterForm, TenancyFilterForm from users.models import User from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES, FilterForm, add_blank_choice @@ -63,7 +64,7 @@ __all__ = ( ) -class DeviceComponentFilterForm(NetBoxModelFilterSetForm): +class DeviceComponentFilterForm(OwnerMixin, NetBoxModelFilterSetForm): name = forms.CharField( label=_('Name'), required=False diff --git a/netbox/dcim/forms/model_forms.py b/netbox/dcim/forms/model_forms.py index a7af27e1d..2d78d44e6 100644 --- a/netbox/dcim/forms/model_forms.py +++ b/netbox/dcim/forms/model_forms.py @@ -11,7 +11,7 @@ from extras.models import ConfigTemplate from ipam.choices import VLANQinQRoleChoices from ipam.models import ASN, IPAddress, VLAN, VLANGroup, VLANTranslationPolicy, VRF from netbox.forms import NestedGroupModelForm, NetBoxModelForm, OrganizationalModelForm, PrimaryModelForm -from netbox.forms.mixins import ChangelogMessageMixin +from netbox.forms.mixins import ChangelogMessageMixin, OwnerMixin from tenancy.forms import TenancyForm from users.models import User from utilities.forms import add_blank_choice, get_field_value @@ -1334,7 +1334,7 @@ class InventoryItemTemplateForm(ComponentTemplateForm): # Device components # -class DeviceComponentForm(NetBoxModelForm): +class DeviceComponentForm(OwnerMixin, NetBoxModelForm): device = DynamicModelChoiceField( label=_('Device'), queryset=Device.objects.all(), diff --git a/netbox/virtualization/forms/bulk_edit.py b/netbox/virtualization/forms/bulk_edit.py index d72d7c2be..092bf576b 100644 --- a/netbox/virtualization/forms/bulk_edit.py +++ b/netbox/virtualization/forms/bulk_edit.py @@ -8,6 +8,7 @@ from dcim.models import Device, DeviceRole, Platform, Site from extras.models import ConfigTemplate from ipam.models import VLAN, VLANGroup, VLANTranslationPolicy, VRF from netbox.forms import NetBoxModelBulkEditForm, OrganizationalModelBulkEditForm, PrimaryModelBulkEditForm +from netbox.forms.mixins import OwnerMixin from tenancy.models import Tenant from utilities.forms import BulkRenameForm, add_blank_choice from utilities.forms.fields import DynamicModelChoiceField, DynamicModelMultipleChoiceField @@ -153,7 +154,7 @@ class VirtualMachineBulkEditForm(PrimaryModelBulkEditForm): ) -class VMInterfaceBulkEditForm(NetBoxModelBulkEditForm): +class VMInterfaceBulkEditForm(OwnerMixin, NetBoxModelBulkEditForm): virtual_machine = forms.ModelChoiceField( label=_('Virtual machine'), queryset=VirtualMachine.objects.all(), @@ -287,7 +288,7 @@ class VMInterfaceBulkRenameForm(BulkRenameForm): ) -class VirtualDiskBulkEditForm(NetBoxModelBulkEditForm): +class VirtualDiskBulkEditForm(OwnerMixin, NetBoxModelBulkEditForm): virtual_machine = forms.ModelChoiceField( label=_('Virtual machine'), queryset=VirtualMachine.objects.all(), diff --git a/netbox/virtualization/forms/bulk_import.py b/netbox/virtualization/forms/bulk_import.py index c058454b5..e64ba4905 100644 --- a/netbox/virtualization/forms/bulk_import.py +++ b/netbox/virtualization/forms/bulk_import.py @@ -5,7 +5,9 @@ from dcim.forms.mixins import ScopedImportForm from dcim.models import Device, DeviceRole, Platform, Site from extras.models import ConfigTemplate from ipam.models import VRF -from netbox.forms import NetBoxModelImportForm, OrganizationalModelBulkImportForm, PrimaryModelBulkImportForm +from netbox.forms import ( + NetBoxModelImportForm, OrganizationalModelBulkImportForm, OwnerCSVMixin, PrimaryModelBulkImportForm, +) from tenancy.models import Tenant from utilities.forms.fields import CSVChoiceField, CSVModelChoiceField from virtualization.choices import * @@ -146,7 +148,7 @@ class VirtualMachineImportForm(PrimaryModelBulkImportForm): ) -class VMInterfaceImportForm(NetBoxModelImportForm): +class VMInterfaceImportForm(OwnerCSVMixin, NetBoxModelImportForm): virtual_machine = CSVModelChoiceField( label=_('Virtual machine'), queryset=VirtualMachine.objects.all(), @@ -184,7 +186,7 @@ class VMInterfaceImportForm(NetBoxModelImportForm): model = VMInterface fields = ( 'virtual_machine', 'name', 'parent', 'bridge', 'enabled', 'mtu', 'description', 'mode', - 'vrf', 'tags' + 'vrf', 'owner', 'tags' ) def __init__(self, data=None, *args, **kwargs): @@ -207,7 +209,7 @@ class VMInterfaceImportForm(NetBoxModelImportForm): return self.cleaned_data['enabled'] -class VirtualDiskImportForm(NetBoxModelImportForm): +class VirtualDiskImportForm(OwnerCSVMixin, NetBoxModelImportForm): virtual_machine = CSVModelChoiceField( label=_('Virtual machine'), queryset=VirtualMachine.objects.all(), @@ -217,5 +219,5 @@ class VirtualDiskImportForm(NetBoxModelImportForm): class Meta: model = VirtualDisk fields = ( - 'virtual_machine', 'name', 'size', 'description', 'tags' + 'virtual_machine', 'name', 'size', 'description', 'owner', 'tags' ) diff --git a/netbox/virtualization/forms/filtersets.py b/netbox/virtualization/forms/filtersets.py index 6741499c0..1b3903075 100644 --- a/netbox/virtualization/forms/filtersets.py +++ b/netbox/virtualization/forms/filtersets.py @@ -7,6 +7,7 @@ from extras.forms import LocalConfigContextFilterForm from extras.models import ConfigTemplate from ipam.models import VRF, VLANTranslationPolicy from netbox.forms import NetBoxModelFilterSetForm, OrganizationalModelFilterSetForm, PrimaryModelFilterSetForm +from netbox.forms.mixins import OwnerMixin from tenancy.forms import ContactModelFilterForm, TenancyFilterForm from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES from utilities.forms.fields import DynamicModelMultipleChoiceField, TagFilterField @@ -199,7 +200,7 @@ class VirtualMachineFilterForm( tag = TagFilterField(model) -class VMInterfaceFilterForm(NetBoxModelFilterSetForm): +class VMInterfaceFilterForm(OwnerMixin, NetBoxModelFilterSetForm): model = VMInterface fieldsets = ( FieldSet('q', 'filter_id', 'tag', 'owner_id'), @@ -256,7 +257,7 @@ class VMInterfaceFilterForm(NetBoxModelFilterSetForm): tag = TagFilterField(model) -class VirtualDiskFilterForm(NetBoxModelFilterSetForm): +class VirtualDiskFilterForm(OwnerMixin, NetBoxModelFilterSetForm): model = VirtualDisk fieldsets = ( FieldSet('q', 'filter_id', 'tag', 'owner_id'), diff --git a/netbox/virtualization/forms/model_forms.py b/netbox/virtualization/forms/model_forms.py index 9b4c21783..fa4966b2b 100644 --- a/netbox/virtualization/forms/model_forms.py +++ b/netbox/virtualization/forms/model_forms.py @@ -11,6 +11,7 @@ from extras.models import ConfigTemplate from ipam.choices import VLANQinQRoleChoices from ipam.models import IPAddress, VLAN, VLANGroup, VLANTranslationPolicy, VRF from netbox.forms import NetBoxModelForm, OrganizationalModelForm, PrimaryModelForm +from netbox.forms.mixins import OwnerMixin from tenancy.forms import TenancyForm from utilities.forms import ConfirmationForm from utilities.forms.fields import DynamicModelChoiceField, DynamicModelMultipleChoiceField, JSONField @@ -280,7 +281,7 @@ class VirtualMachineForm(TenancyForm, PrimaryModelForm): # Virtual machine components # -class VMComponentForm(NetBoxModelForm): +class VMComponentForm(OwnerMixin, NetBoxModelForm): virtual_machine = DynamicModelChoiceField( label=_('Virtual machine'), queryset=VirtualMachine.objects.all(),