From a848d3b81645879bd613f1d0679c0f6bf0ec7f84 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 21 Oct 2025 16:15:26 -0400 Subject: [PATCH] Add owner field to all applicable bulk import forms --- netbox/circuits/forms/bulk_import.py | 37 ++++--- netbox/core/forms/bulk_import.py | 6 +- netbox/dcim/forms/bulk_import.py | 108 +++++++++++---------- netbox/extras/forms/bulk_import.py | 42 ++++---- netbox/ipam/forms/bulk_import.py | 70 +++++++------ netbox/netbox/forms/bulk_import.py | 43 ++++++-- netbox/tenancy/forms/bulk_import.py | 30 +++--- netbox/virtualization/forms/bulk_import.py | 23 +++-- netbox/vpn/forms/bulk_import.py | 40 ++++---- netbox/wireless/forms/bulk_import.py | 18 ++-- 10 files changed, 223 insertions(+), 194 deletions(-) diff --git a/netbox/circuits/forms/bulk_import.py b/netbox/circuits/forms/bulk_import.py index 43700d16b..4f5295982 100644 --- a/netbox/circuits/forms/bulk_import.py +++ b/netbox/circuits/forms/bulk_import.py @@ -7,7 +7,7 @@ from circuits.constants import * from circuits.models import * from dcim.models import Interface from netbox.choices import DistanceUnitChoices -from netbox.forms import NetBoxModelImportForm +from netbox.forms import NetBoxModelImportForm, OrganizationalModelBulkImportForm, PrimaryModelBulkImportForm from tenancy.models import Tenant from utilities.forms.fields import CSVChoiceField, CSVContentTypeField, CSVModelChoiceField, SlugField @@ -28,17 +28,17 @@ __all__ = ( ) -class ProviderImportForm(NetBoxModelImportForm): +class ProviderImportForm(PrimaryModelBulkImportForm): slug = SlugField() class Meta: model = Provider fields = ( - 'name', 'slug', 'description', 'comments', 'tags', + 'name', 'slug', 'description', 'owner', 'comments', 'tags', ) -class ProviderAccountImportForm(NetBoxModelImportForm): +class ProviderAccountImportForm(PrimaryModelBulkImportForm): provider = CSVModelChoiceField( label=_('Provider'), queryset=Provider.objects.all(), @@ -49,11 +49,11 @@ class ProviderAccountImportForm(NetBoxModelImportForm): class Meta: model = ProviderAccount fields = ( - 'provider', 'name', 'account', 'description', 'comments', 'tags', + 'provider', 'name', 'account', 'description', 'owner', 'comments', 'tags', ) -class ProviderNetworkImportForm(NetBoxModelImportForm): +class ProviderNetworkImportForm(PrimaryModelBulkImportForm): provider = CSVModelChoiceField( label=_('Provider'), queryset=Provider.objects.all(), @@ -64,19 +64,19 @@ class ProviderNetworkImportForm(NetBoxModelImportForm): class Meta: model = ProviderNetwork fields = [ - 'provider', 'name', 'service_id', 'description', 'comments', 'tags' + 'provider', 'name', 'service_id', 'description', 'owner', 'comments', 'tags' ] -class CircuitTypeImportForm(NetBoxModelImportForm): +class CircuitTypeImportForm(OrganizationalModelBulkImportForm): slug = SlugField() class Meta: model = CircuitType - fields = ('name', 'slug', 'color', 'description', 'tags') + fields = ('name', 'slug', 'color', 'description', 'owner', 'tags') -class CircuitImportForm(NetBoxModelImportForm): +class CircuitImportForm(PrimaryModelBulkImportForm): provider = CSVModelChoiceField( label=_('Provider'), queryset=Provider.objects.all(), @@ -119,7 +119,7 @@ class CircuitImportForm(NetBoxModelImportForm): model = Circuit fields = [ 'cid', 'provider', 'provider_account', 'type', 'status', 'tenant', 'install_date', 'termination_date', - 'commit_rate', 'distance', 'distance_unit', 'description', 'comments', 'tags' + 'commit_rate', 'distance', 'distance_unit', 'description', 'owner', 'comments', 'tags' ] @@ -165,7 +165,7 @@ class CircuitTerminationImportForm(NetBoxModelImportForm, BaseCircuitTermination } -class CircuitGroupImportForm(NetBoxModelImportForm): +class CircuitGroupImportForm(OrganizationalModelBulkImportForm): tenant = CSVModelChoiceField( label=_('Tenant'), queryset=Tenant.objects.all(), @@ -176,7 +176,7 @@ class CircuitGroupImportForm(NetBoxModelImportForm): class Meta: model = CircuitGroup - fields = ('name', 'slug', 'description', 'tenant', 'tags') + fields = ('name', 'slug', 'description', 'tenant', 'owner', 'tags') class CircuitGroupAssignmentImportForm(NetBoxModelImportForm): @@ -195,15 +195,14 @@ class CircuitGroupAssignmentImportForm(NetBoxModelImportForm): fields = ('member_type', 'member_id', 'group', 'priority') -class VirtualCircuitTypeImportForm(NetBoxModelImportForm): - slug = SlugField() +class VirtualCircuitTypeImportForm(OrganizationalModelBulkImportForm): class Meta: model = VirtualCircuitType - fields = ('name', 'slug', 'color', 'description', 'tags') + fields = ('name', 'slug', 'color', 'description', 'owner', 'tags') -class VirtualCircuitImportForm(NetBoxModelImportForm): +class VirtualCircuitImportForm(PrimaryModelBulkImportForm): provider_network = CSVModelChoiceField( label=_('Provider network'), queryset=ProviderNetwork.objects.all(), @@ -239,8 +238,8 @@ class VirtualCircuitImportForm(NetBoxModelImportForm): class Meta: model = VirtualCircuit fields = [ - 'cid', 'provider_network', 'provider_account', 'type', 'status', 'tenant', 'description', 'comments', - 'tags', + 'cid', 'provider_network', 'provider_account', 'type', 'status', 'tenant', 'description', 'owner', + 'comments', 'tags', ] diff --git a/netbox/core/forms/bulk_import.py b/netbox/core/forms/bulk_import.py index a5791c945..c9311a61d 100644 --- a/netbox/core/forms/bulk_import.py +++ b/netbox/core/forms/bulk_import.py @@ -1,16 +1,16 @@ from core.models import * -from netbox.forms import NetBoxModelImportForm +from netbox.forms import PrimaryModelBulkImportForm __all__ = ( 'DataSourceImportForm', ) -class DataSourceImportForm(NetBoxModelImportForm): +class DataSourceImportForm(PrimaryModelBulkImportForm): class Meta: model = DataSource fields = ( 'name', 'type', 'source_url', 'enabled', 'description', 'sync_interval', 'parameters', 'ignore_rules', - 'comments', + 'owner', 'comments', ) diff --git a/netbox/dcim/forms/bulk_import.py b/netbox/dcim/forms/bulk_import.py index 10ae701bb..65abd9502 100644 --- a/netbox/dcim/forms/bulk_import.py +++ b/netbox/dcim/forms/bulk_import.py @@ -11,7 +11,10 @@ from dcim.models import * from extras.models import ConfigTemplate from ipam.models import VRF, IPAddress from netbox.choices import * -from netbox.forms import NetBoxModelImportForm +from netbox.forms import ( + NestedGroupModelBulkImportForm, NetBoxModelImportForm, OrganizationalModelBulkImportForm, + PrimaryModelBulkImportForm, +) from tenancy.models import Tenant from utilities.forms.fields import ( CSVChoiceField, CSVContentTypeField, CSVModelChoiceField, CSVModelMultipleChoiceField, CSVTypedChoiceField, @@ -58,7 +61,7 @@ __all__ = ( ) -class RegionImportForm(NetBoxModelImportForm): +class RegionImportForm(NestedGroupModelBulkImportForm): parent = CSVModelChoiceField( label=_('Parent'), queryset=Region.objects.all(), @@ -69,10 +72,10 @@ class RegionImportForm(NetBoxModelImportForm): class Meta: model = Region - fields = ('name', 'slug', 'parent', 'description', 'tags', 'comments') + fields = ('name', 'slug', 'parent', 'description', 'owner', 'comments', 'tags') -class SiteGroupImportForm(NetBoxModelImportForm): +class SiteGroupImportForm(NestedGroupModelBulkImportForm): parent = CSVModelChoiceField( label=_('Parent'), queryset=SiteGroup.objects.all(), @@ -83,10 +86,10 @@ class SiteGroupImportForm(NetBoxModelImportForm): class Meta: model = SiteGroup - fields = ('name', 'slug', 'parent', 'description', 'comments', 'tags') + fields = ('name', 'slug', 'parent', 'description', 'owner', 'comments', 'tags') -class SiteImportForm(NetBoxModelImportForm): +class SiteImportForm(PrimaryModelBulkImportForm): status = CSVChoiceField( label=_('Status'), choices=SiteStatusChoices, @@ -118,7 +121,7 @@ class SiteImportForm(NetBoxModelImportForm): model = Site fields = ( 'name', 'slug', 'status', 'region', 'group', 'tenant', 'facility', 'time_zone', 'description', - 'physical_address', 'shipping_address', 'latitude', 'longitude', 'comments', 'tags' + 'physical_address', 'shipping_address', 'latitude', 'longitude', 'owner', 'comments', 'tags' ) help_texts = { 'time_zone': mark_safe( @@ -129,7 +132,7 @@ class SiteImportForm(NetBoxModelImportForm): } -class LocationImportForm(NetBoxModelImportForm): +class LocationImportForm(NestedGroupModelBulkImportForm): site = CSVModelChoiceField( label=_('Site'), queryset=Site.objects.all(), @@ -162,8 +165,8 @@ class LocationImportForm(NetBoxModelImportForm): class Meta: model = Location fields = ( - 'site', 'parent', 'name', 'slug', 'status', 'tenant', 'facility', 'description', - 'tags', 'comments', + 'site', 'parent', 'name', 'slug', 'status', 'tenant', 'facility', 'description', 'owner', 'comments', + 'tags', ) def __init__(self, data=None, *args, **kwargs): @@ -175,15 +178,14 @@ class LocationImportForm(NetBoxModelImportForm): self.fields['parent'].queryset = self.fields['parent'].queryset.filter(**params) -class RackRoleImportForm(NetBoxModelImportForm): - slug = SlugField() +class RackRoleImportForm(OrganizationalModelBulkImportForm): class Meta: model = RackRole - fields = ('name', 'slug', 'color', 'description', 'tags') + fields = ('name', 'slug', 'color', 'description', 'owner', 'tags') -class RackTypeImportForm(NetBoxModelImportForm): +class RackTypeImportForm(PrimaryModelBulkImportForm): manufacturer = forms.ModelChoiceField( label=_('Manufacturer'), queryset=Manufacturer.objects.all(), @@ -224,14 +226,14 @@ class RackTypeImportForm(NetBoxModelImportForm): fields = ( 'manufacturer', 'model', 'slug', 'form_factor', 'width', 'u_height', 'starting_unit', 'desc_units', 'outer_width', 'outer_height', 'outer_depth', 'outer_unit', 'mounting_depth', 'weight', 'max_weight', - 'weight_unit', 'description', 'comments', 'tags', + 'weight_unit', 'description', 'owner', 'comments', 'tags', ) def __init__(self, data=None, *args, **kwargs): super().__init__(data, *args, **kwargs) -class RackImportForm(NetBoxModelImportForm): +class RackImportForm(PrimaryModelBulkImportForm): site = CSVModelChoiceField( label=_('Site'), queryset=Site.objects.all(), @@ -309,7 +311,8 @@ class RackImportForm(NetBoxModelImportForm): fields = ( 'site', 'location', 'name', 'facility_id', 'tenant', 'status', 'role', 'rack_type', 'form_factor', 'serial', 'asset_tag', 'width', 'u_height', 'desc_units', 'outer_width', 'outer_height', 'outer_depth', 'outer_unit', - 'mounting_depth', 'airflow', 'weight', 'max_weight', 'weight_unit', 'description', 'comments', 'tags', + 'mounting_depth', 'airflow', 'weight', 'max_weight', 'weight_unit', 'description', 'owner', 'comments', + 'tags', ) def __init__(self, data=None, *args, **kwargs): @@ -332,7 +335,7 @@ class RackImportForm(NetBoxModelImportForm): raise forms.ValidationError(_("U height must be set if not specifying a rack type.")) -class RackReservationImportForm(NetBoxModelImportForm): +class RackReservationImportForm(PrimaryModelBulkImportForm): site = CSVModelChoiceField( label=_('Site'), queryset=Site.objects.all(), @@ -373,7 +376,7 @@ class RackReservationImportForm(NetBoxModelImportForm): class Meta: model = RackReservation - fields = ('site', 'location', 'rack', 'units', 'status', 'tenant', 'description', 'comments', 'tags') + fields = ('site', 'location', 'rack', 'units', 'status', 'tenant', 'description', 'owner', 'comments', 'tags') def __init__(self, data=None, *args, **kwargs): super().__init__(data, *args, **kwargs) @@ -392,14 +395,14 @@ class RackReservationImportForm(NetBoxModelImportForm): self.fields['rack'].queryset = self.fields['rack'].queryset.filter(**params) -class ManufacturerImportForm(NetBoxModelImportForm): +class ManufacturerImportForm(OrganizationalModelBulkImportForm): class Meta: model = Manufacturer - fields = ('name', 'slug', 'description', 'tags') + fields = ('name', 'slug', 'description', 'owner', 'tags') -class DeviceTypeImportForm(NetBoxModelImportForm): +class DeviceTypeImportForm(PrimaryModelBulkImportForm): manufacturer = CSVModelChoiceField( label=_('Manufacturer'), queryset=Manufacturer.objects.all(), @@ -429,20 +432,21 @@ class DeviceTypeImportForm(NetBoxModelImportForm): model = DeviceType fields = [ 'manufacturer', 'default_platform', 'model', 'slug', 'part_number', 'u_height', 'exclude_from_utilization', - 'is_full_depth', 'subdevice_role', 'airflow', 'description', 'weight', 'weight_unit', 'comments', 'tags', + 'is_full_depth', 'subdevice_role', 'airflow', 'description', 'weight', 'weight_unit', 'owner', 'comments', + 'tags', ] -class ModuleTypeProfileImportForm(NetBoxModelImportForm): +class ModuleTypeProfileImportForm(PrimaryModelBulkImportForm): class Meta: model = ModuleTypeProfile fields = [ - 'name', 'description', 'schema', 'comments', 'tags', + 'name', 'description', 'schema', 'owner', 'comments', 'tags', ] -class ModuleTypeImportForm(NetBoxModelImportForm): +class ModuleTypeImportForm(PrimaryModelBulkImportForm): profile = forms.ModelChoiceField( label=_('Profile'), queryset=ModuleTypeProfile.objects.all(), @@ -476,11 +480,11 @@ class ModuleTypeImportForm(NetBoxModelImportForm): model = ModuleType fields = [ 'manufacturer', 'model', 'part_number', 'description', 'airflow', 'weight', 'weight_unit', 'profile', - 'comments', 'tags' + 'owner', 'comments', 'tags' ] -class DeviceRoleImportForm(NetBoxModelImportForm): +class DeviceRoleImportForm(NestedGroupModelBulkImportForm): parent = CSVModelChoiceField( label=_('Parent'), queryset=DeviceRole.objects.all(), @@ -498,17 +502,15 @@ class DeviceRoleImportForm(NetBoxModelImportForm): required=False, help_text=_('Config template') ) - slug = SlugField() class Meta: model = DeviceRole fields = ( - 'name', 'slug', 'parent', 'color', 'vm_role', 'config_template', 'description', 'comments', 'tags' + 'name', 'slug', 'parent', 'color', 'vm_role', 'config_template', 'description', 'owner', 'comments', 'tags' ) -class PlatformImportForm(NetBoxModelImportForm): - slug = SlugField() +class PlatformImportForm(NestedGroupModelBulkImportForm): parent = CSVModelChoiceField( label=_('Parent'), queryset=Platform.objects.all(), @@ -537,11 +539,11 @@ class PlatformImportForm(NetBoxModelImportForm): class Meta: model = Platform fields = ( - 'name', 'slug', 'parent', 'manufacturer', 'config_template', 'description', 'tags', + 'name', 'slug', 'parent', 'manufacturer', 'config_template', 'description', 'owner', 'comments', 'tags', ) -class BaseDeviceImportForm(NetBoxModelImportForm): +class BaseDeviceImportForm(PrimaryModelBulkImportForm): role = CSVModelChoiceField( label=_('Device role'), queryset=DeviceRole.objects.all(), @@ -667,8 +669,8 @@ class DeviceImportForm(BaseDeviceImportForm): fields = [ 'name', 'role', 'tenant', 'manufacturer', 'device_type', 'platform', 'serial', 'asset_tag', 'status', 'site', 'location', 'rack', 'position', 'face', 'latitude', 'longitude', 'parent', 'device_bay', 'airflow', - 'virtual_chassis', 'vc_position', 'vc_priority', 'cluster', 'description', 'config_template', 'comments', - 'tags', + 'virtual_chassis', 'vc_position', 'vc_priority', 'cluster', 'description', 'config_template', 'owner', + 'comments', 'tags', ] def __init__(self, data=None, *args, **kwargs): @@ -715,7 +717,7 @@ class DeviceImportForm(BaseDeviceImportForm): self.instance.parent_bay = device_bay -class ModuleImportForm(ModuleCommonForm, NetBoxModelImportForm): +class ModuleImportForm(ModuleCommonForm, PrimaryModelBulkImportForm): device = CSVModelChoiceField( label=_('Device'), queryset=Device.objects.all(), @@ -753,7 +755,7 @@ class ModuleImportForm(ModuleCommonForm, NetBoxModelImportForm): class Meta: model = Module fields = ( - 'device', 'module_bay', 'module_type', 'serial', 'asset_tag', 'status', 'description', 'comments', + 'device', 'module_bay', 'module_type', 'serial', 'asset_tag', 'status', 'description', 'owner', 'comments', 'replicate_components', 'adopt_components', 'tags', ) @@ -1148,7 +1150,7 @@ class DeviceBayImportForm(NetBoxModelImportForm): self.fields['installed_device'].queryset = Device.objects.none() -class InventoryItemImportForm(NetBoxModelImportForm): +class InventoryItemImportForm(OrganizationalModelBulkImportForm): device = CSVModelChoiceField( label=_('Device'), queryset=Device.objects.all(), @@ -1195,7 +1197,7 @@ class InventoryItemImportForm(NetBoxModelImportForm): model = InventoryItem fields = ( 'device', 'name', 'label', 'status', 'role', 'manufacturer', 'parent', 'part_id', 'serial', 'asset_tag', - 'discovered', 'description', 'tags', 'component_type', 'component_name', + 'discovered', 'description', 'owner', 'tags', 'component_type', 'component_name', ) def __init__(self, *args, **kwargs): @@ -1270,7 +1272,7 @@ class InventoryItemRoleImportForm(NetBoxModelImportForm): # Addressing # -class MACAddressImportForm(NetBoxModelImportForm): +class MACAddressImportForm(PrimaryModelBulkImportForm): device = CSVModelChoiceField( label=_('Device'), queryset=Device.objects.all(), @@ -1301,7 +1303,8 @@ class MACAddressImportForm(NetBoxModelImportForm): class Meta: model = MACAddress fields = [ - 'mac_address', 'device', 'virtual_machine', 'interface', 'is_primary', 'description', 'comments', 'tags', + 'mac_address', 'device', 'virtual_machine', 'interface', 'is_primary', 'description', 'owner', 'comments', + 'tags', ] def __init__(self, data=None, *args, **kwargs): @@ -1354,7 +1357,7 @@ class MACAddressImportForm(NetBoxModelImportForm): # Cables # -class CableImportForm(NetBoxModelImportForm): +class CableImportForm(PrimaryModelBulkImportForm): # Termination A side_a_site = CSVModelChoiceField( label=_('Side A site'), @@ -1443,7 +1446,7 @@ class CableImportForm(NetBoxModelImportForm): fields = [ 'side_a_site', 'side_a_device', 'side_a_type', 'side_a_name', 'side_b_site', 'side_b_device', 'side_b_type', 'side_b_name', 'type', 'status', 'tenant', 'label', 'color', 'length', 'length_unit', 'description', - 'comments', 'tags', + 'owner', 'comments', 'tags', ] def __init__(self, data=None, *args, **kwargs): @@ -1537,7 +1540,7 @@ class CableImportForm(NetBoxModelImportForm): # -class VirtualChassisImportForm(NetBoxModelImportForm): +class VirtualChassisImportForm(PrimaryModelBulkImportForm): master = CSVModelChoiceField( label=_('Master'), queryset=Device.objects.all(), @@ -1548,14 +1551,14 @@ class VirtualChassisImportForm(NetBoxModelImportForm): class Meta: model = VirtualChassis - fields = ('name', 'domain', 'master', 'description', 'comments', 'tags') + fields = ('name', 'domain', 'master', 'description', 'owner', 'comments', 'tags') # # Power # -class PowerPanelImportForm(NetBoxModelImportForm): +class PowerPanelImportForm(PrimaryModelBulkImportForm): site = CSVModelChoiceField( label=_('Site'), queryset=Site.objects.all(), @@ -1571,7 +1574,7 @@ class PowerPanelImportForm(NetBoxModelImportForm): class Meta: model = PowerPanel - fields = ('site', 'location', 'name', 'description', 'comments', 'tags') + fields = ('site', 'location', 'name', 'description', 'owner', 'comments', 'tags') def __init__(self, data=None, *args, **kwargs): super().__init__(data, *args, **kwargs) @@ -1583,7 +1586,7 @@ class PowerPanelImportForm(NetBoxModelImportForm): self.fields['location'].queryset = self.fields['location'].queryset.filter(**params) -class PowerFeedImportForm(NetBoxModelImportForm): +class PowerFeedImportForm(PrimaryModelBulkImportForm): site = CSVModelChoiceField( label=_('Site'), queryset=Site.objects.all(), @@ -1641,7 +1644,7 @@ class PowerFeedImportForm(NetBoxModelImportForm): model = PowerFeed fields = ( 'site', 'power_panel', 'location', 'rack', 'name', 'status', 'type', 'mark_connected', 'supply', 'phase', - 'voltage', 'amperage', 'max_utilization', 'tenant', 'description', 'comments', 'tags', + 'voltage', 'amperage', 'max_utilization', 'tenant', 'description', 'owner', 'comments', 'tags', ) def __init__(self, data=None, *args, **kwargs): @@ -1665,8 +1668,7 @@ class PowerFeedImportForm(NetBoxModelImportForm): self.fields['rack'].queryset = self.fields['rack'].queryset.filter(**params) -class VirtualDeviceContextImportForm(NetBoxModelImportForm): - +class VirtualDeviceContextImportForm(PrimaryModelBulkImportForm): device = CSVModelChoiceField( label=_('Device'), queryset=Device.objects.all(), @@ -1701,7 +1703,7 @@ class VirtualDeviceContextImportForm(NetBoxModelImportForm): class Meta: fields = [ - 'name', 'device', 'status', 'tenant', 'identifier', 'comments', 'primary_ip4', 'primary_ip6', + 'name', 'device', 'status', 'tenant', 'identifier', 'owner', 'comments', 'primary_ip4', 'primary_ip6', ] model = VirtualDeviceContext diff --git a/netbox/extras/forms/bulk_import.py b/netbox/extras/forms/bulk_import.py index 4f7c85e85..8b6420b4c 100644 --- a/netbox/extras/forms/bulk_import.py +++ b/netbox/extras/forms/bulk_import.py @@ -9,7 +9,7 @@ from core.models import ObjectType from extras.choices import * from extras.models import * from netbox.events import get_event_type_choices -from netbox.forms import NetBoxModelImportForm +from netbox.forms import NetBoxModelImportForm, OwnerCSVMixin, PrimaryModelBulkImportForm from users.models import Group, User from utilities.forms import CSVModelForm from utilities.forms.fields import ( @@ -33,7 +33,7 @@ __all__ = ( ) -class CustomFieldImportForm(CSVModelForm): +class CustomFieldImportForm(OwnerCSVMixin, CSVModelForm): object_types = CSVMultipleContentTypeField( label=_('Object types'), queryset=ObjectType.objects.with_feature('custom_fields'), @@ -75,11 +75,11 @@ class CustomFieldImportForm(CSVModelForm): fields = ( 'name', 'label', 'group_name', 'type', 'object_types', 'related_object_type', 'required', 'unique', 'description', 'search_weight', 'filter_logic', 'default', 'choice_set', 'weight', 'validation_minimum', - 'validation_maximum', 'validation_regex', 'ui_visible', 'ui_editable', 'is_cloneable', 'comments', + 'validation_maximum', 'validation_regex', 'ui_visible', 'ui_editable', 'is_cloneable', 'owner', 'comments', ) -class CustomFieldChoiceSetImportForm(CSVModelForm): +class CustomFieldChoiceSetImportForm(OwnerCSVMixin, CSVModelForm): base_choices = CSVChoiceField( choices=CustomFieldChoiceSetBaseChoices, required=False, @@ -97,7 +97,7 @@ class CustomFieldChoiceSetImportForm(CSVModelForm): class Meta: model = CustomFieldChoiceSet fields = ( - 'name', 'description', 'base_choices', 'extra_choices', 'order_alphabetically', + 'name', 'description', 'base_choices', 'extra_choices', 'order_alphabetically', 'owner', ) def clean_extra_choices(self): @@ -114,7 +114,7 @@ class CustomFieldChoiceSetImportForm(CSVModelForm): return data -class CustomLinkImportForm(CSVModelForm): +class CustomLinkImportForm(OwnerCSVMixin, CSVModelForm): object_types = CSVMultipleContentTypeField( label=_('Object types'), queryset=ObjectType.objects.with_feature('custom_links'), @@ -131,11 +131,11 @@ class CustomLinkImportForm(CSVModelForm): model = CustomLink fields = ( 'name', 'object_types', 'enabled', 'weight', 'group_name', 'button_class', 'new_window', 'link_text', - 'link_url', + 'link_url', 'owner', ) -class ExportTemplateImportForm(CSVModelForm): +class ExportTemplateImportForm(OwnerCSVMixin, CSVModelForm): object_types = CSVMultipleContentTypeField( label=_('Object types'), queryset=ObjectType.objects.with_feature('export_templates'), @@ -146,30 +146,30 @@ class ExportTemplateImportForm(CSVModelForm): model = ExportTemplate fields = ( 'name', 'object_types', 'description', 'environment_params', 'mime_type', 'file_name', 'file_extension', - 'as_attachment', 'template_code', + 'as_attachment', 'template_code', 'owner', ) -class ConfigContextProfileImportForm(NetBoxModelImportForm): +class ConfigContextProfileImportForm(PrimaryModelBulkImportForm): class Meta: model = ConfigContextProfile fields = [ - 'name', 'description', 'schema', 'comments', 'tags', + 'name', 'description', 'schema', 'owner', 'comments', 'tags', ] -class ConfigTemplateImportForm(CSVModelForm): +class ConfigTemplateImportForm(OwnerCSVMixin, CSVModelForm): class Meta: model = ConfigTemplate fields = ( 'name', 'description', 'template_code', 'environment_params', 'mime_type', 'file_name', 'file_extension', - 'as_attachment', 'tags', + 'as_attachment', 'owner', 'tags', ) -class SavedFilterImportForm(CSVModelForm): +class SavedFilterImportForm(OwnerCSVMixin, CSVModelForm): object_types = CSVMultipleContentTypeField( label=_('Object types'), queryset=ObjectType.objects.all(), @@ -179,21 +179,21 @@ class SavedFilterImportForm(CSVModelForm): class Meta: model = SavedFilter fields = ( - 'name', 'slug', 'object_types', 'description', 'weight', 'enabled', 'shared', 'parameters', + 'name', 'slug', 'object_types', 'description', 'weight', 'enabled', 'shared', 'parameters', 'owner', ) -class WebhookImportForm(NetBoxModelImportForm): +class WebhookImportForm(OwnerCSVMixin, NetBoxModelImportForm): class Meta: model = Webhook fields = ( 'name', 'payload_url', 'http_method', 'http_content_type', 'additional_headers', 'body_template', - 'secret', 'ssl_verification', 'ca_file_path', 'description', 'tags' + 'secret', 'ssl_verification', 'ca_file_path', 'description', 'owner', 'tags' ) -class EventRuleImportForm(NetBoxModelImportForm): +class EventRuleImportForm(OwnerCSVMixin, NetBoxModelImportForm): object_types = CSVMultipleContentTypeField( label=_('Object types'), queryset=ObjectType.objects.with_feature('event_rules'), @@ -214,7 +214,7 @@ class EventRuleImportForm(NetBoxModelImportForm): model = EventRule fields = ( 'name', 'description', 'enabled', 'conditions', 'object_types', 'event_types', 'action_type', - 'comments', 'tags' + 'owner', 'comments', 'tags' ) def clean(self): @@ -242,7 +242,7 @@ class EventRuleImportForm(NetBoxModelImportForm): self.instance.action_object_type = ObjectType.objects.get_for_model(script, for_concrete_model=False) -class TagImportForm(CSVModelForm): +class TagImportForm(OwnerCSVMixin, CSVModelForm): slug = SlugField() weight = forms.IntegerField( label=_('Weight'), @@ -258,7 +258,7 @@ class TagImportForm(CSVModelForm): class Meta: model = Tag fields = ( - 'name', 'slug', 'color', 'weight', 'description', 'object_types', + 'name', 'slug', 'color', 'weight', 'description', 'object_types', 'owner', ) diff --git a/netbox/ipam/forms/bulk_import.py b/netbox/ipam/forms/bulk_import.py index c0aa43461..f2db5a52b 100644 --- a/netbox/ipam/forms/bulk_import.py +++ b/netbox/ipam/forms/bulk_import.py @@ -7,7 +7,7 @@ from dcim.forms.mixins import ScopedImportForm from ipam.choices import * from ipam.constants import * from ipam.models import * -from netbox.forms import NetBoxModelImportForm +from netbox.forms import NetBoxModelImportForm, OrganizationalModelBulkImportForm, PrimaryModelBulkImportForm from tenancy.models import Tenant from utilities.forms.fields import ( CSVChoiceField, CSVContentTypeField, CSVModelChoiceField, CSVModelMultipleChoiceField, SlugField, @@ -36,7 +36,7 @@ __all__ = ( ) -class VRFImportForm(NetBoxModelImportForm): +class VRFImportForm(PrimaryModelBulkImportForm): tenant = CSVModelChoiceField( label=_('Tenant'), queryset=Tenant.objects.all(), @@ -60,12 +60,12 @@ class VRFImportForm(NetBoxModelImportForm): class Meta: model = VRF fields = ( - 'name', 'rd', 'tenant', 'enforce_unique', 'description', 'import_targets', 'export_targets', 'comments', - 'tags', + 'name', 'rd', 'tenant', 'enforce_unique', 'description', 'import_targets', 'export_targets', 'owner', + 'comments', 'tags', ) -class RouteTargetImportForm(NetBoxModelImportForm): +class RouteTargetImportForm(PrimaryModelBulkImportForm): tenant = CSVModelChoiceField( label=_('Tenant'), queryset=Tenant.objects.all(), @@ -76,18 +76,18 @@ class RouteTargetImportForm(NetBoxModelImportForm): class Meta: model = RouteTarget - fields = ('name', 'tenant', 'description', 'comments', 'tags') + fields = ('name', 'tenant', 'description', 'owner', 'comments', 'tags') -class RIRImportForm(NetBoxModelImportForm): +class RIRImportForm(OrganizationalModelBulkImportForm): slug = SlugField() class Meta: model = RIR - fields = ('name', 'slug', 'is_private', 'description', 'tags') + fields = ('name', 'slug', 'is_private', 'description', 'owner', 'tags') -class AggregateImportForm(NetBoxModelImportForm): +class AggregateImportForm(PrimaryModelBulkImportForm): rir = CSVModelChoiceField( label=_('RIR'), queryset=RIR.objects.all(), @@ -104,10 +104,10 @@ class AggregateImportForm(NetBoxModelImportForm): class Meta: model = Aggregate - fields = ('prefix', 'rir', 'tenant', 'date_added', 'description', 'comments', 'tags') + fields = ('prefix', 'rir', 'tenant', 'date_added', 'description', 'owner', 'comments', 'tags') -class ASNRangeImportForm(NetBoxModelImportForm): +class ASNRangeImportForm(OrganizationalModelBulkImportForm): rir = CSVModelChoiceField( label=_('RIR'), queryset=RIR.objects.all(), @@ -124,10 +124,10 @@ class ASNRangeImportForm(NetBoxModelImportForm): class Meta: model = ASNRange - fields = ('name', 'slug', 'rir', 'start', 'end', 'tenant', 'description', 'tags') + fields = ('name', 'slug', 'rir', 'start', 'end', 'tenant', 'description', 'owner', 'tags') -class ASNImportForm(NetBoxModelImportForm): +class ASNImportForm(PrimaryModelBulkImportForm): rir = CSVModelChoiceField( label=_('RIR'), queryset=RIR.objects.all(), @@ -144,18 +144,17 @@ class ASNImportForm(NetBoxModelImportForm): class Meta: model = ASN - fields = ('asn', 'rir', 'tenant', 'description', 'comments', 'tags') + fields = ('asn', 'rir', 'tenant', 'description', 'owner', 'comments', 'tags') -class RoleImportForm(NetBoxModelImportForm): - slug = SlugField() +class RoleImportForm(OrganizationalModelBulkImportForm): class Meta: model = Role - fields = ('name', 'slug', 'weight', 'description', 'tags') + fields = ('name', 'slug', 'weight', 'description', 'owner', 'tags') -class PrefixImportForm(ScopedImportForm, NetBoxModelImportForm): +class PrefixImportForm(ScopedImportForm, PrimaryModelBulkImportForm): vrf = CSVModelChoiceField( label=_('VRF'), queryset=VRF.objects.all(), @@ -208,7 +207,7 @@ class PrefixImportForm(ScopedImportForm, NetBoxModelImportForm): model = Prefix fields = ( 'prefix', 'vrf', 'tenant', 'vlan_group', 'vlan_site', 'vlan', 'status', 'role', 'scope_type', 'scope_id', - 'is_pool', 'mark_utilized', 'description', 'comments', 'tags', + 'is_pool', 'mark_utilized', 'description', 'owner', 'comments', 'tags', ) labels = { 'scope_id': _('Scope ID'), @@ -244,7 +243,7 @@ class PrefixImportForm(ScopedImportForm, NetBoxModelImportForm): self.fields['vlan'].queryset = queryset -class IPRangeImportForm(NetBoxModelImportForm): +class IPRangeImportForm(PrimaryModelBulkImportForm): vrf = CSVModelChoiceField( label=_('VRF'), queryset=VRF.objects.all(), @@ -276,11 +275,11 @@ class IPRangeImportForm(NetBoxModelImportForm): model = IPRange fields = ( 'start_address', 'end_address', 'vrf', 'tenant', 'status', 'role', 'mark_populated', 'mark_utilized', - 'description', 'comments', 'tags', + 'description', 'owner', 'comments', 'tags', ) -class IPAddressImportForm(NetBoxModelImportForm): +class IPAddressImportForm(PrimaryModelBulkImportForm): vrf = CSVModelChoiceField( label=_('VRF'), queryset=VRF.objects.all(), @@ -349,7 +348,7 @@ class IPAddressImportForm(NetBoxModelImportForm): model = IPAddress fields = [ 'address', 'vrf', 'tenant', 'status', 'role', 'device', 'virtual_machine', 'interface', 'fhrp_group', - 'is_primary', 'is_oob', 'dns_name', 'description', 'comments', 'tags', + 'is_primary', 'is_oob', 'dns_name', 'description', 'owner', 'comments', 'tags', ] def __init__(self, data=None, *args, **kwargs): @@ -428,7 +427,7 @@ class IPAddressImportForm(NetBoxModelImportForm): return ipaddress -class FHRPGroupImportForm(NetBoxModelImportForm): +class FHRPGroupImportForm(PrimaryModelBulkImportForm): protocol = CSVChoiceField( label=_('Protocol'), choices=FHRPGroupProtocolChoices @@ -441,11 +440,10 @@ class FHRPGroupImportForm(NetBoxModelImportForm): class Meta: model = FHRPGroup - fields = ('protocol', 'group_id', 'auth_type', 'auth_key', 'name', 'description', 'comments', 'tags') + fields = ('protocol', 'group_id', 'auth_type', 'auth_key', 'name', 'description', 'owner', 'comments', 'tags') -class VLANGroupImportForm(NetBoxModelImportForm): - slug = SlugField() +class VLANGroupImportForm(OrganizationalModelBulkImportForm): scope_type = CSVContentTypeField( queryset=ContentType.objects.filter(model__in=VLANGROUP_SCOPE_TYPES), required=False, @@ -464,13 +462,13 @@ class VLANGroupImportForm(NetBoxModelImportForm): class Meta: model = VLANGroup - fields = ('name', 'slug', 'scope_type', 'scope_id', 'vid_ranges', 'tenant', 'description', 'tags') + fields = ('name', 'slug', 'scope_type', 'scope_id', 'vid_ranges', 'tenant', 'description', 'owner', 'tags') labels = { 'scope_id': 'Scope ID', } -class VLANImportForm(NetBoxModelImportForm): +class VLANImportForm(PrimaryModelBulkImportForm): site = CSVModelChoiceField( label=_('Site'), queryset=Site.objects.all(), @@ -522,15 +520,15 @@ class VLANImportForm(NetBoxModelImportForm): model = VLAN fields = ( 'site', 'group', 'vid', 'name', 'tenant', 'status', 'role', 'description', 'qinq_role', 'qinq_svlan', - 'comments', 'tags', + 'owner', 'comments', 'tags', ) -class VLANTranslationPolicyImportForm(NetBoxModelImportForm): +class VLANTranslationPolicyImportForm(PrimaryModelBulkImportForm): class Meta: model = VLANTranslationPolicy - fields = ('name', 'description', 'tags') + fields = ('name', 'description', 'owner', 'comments', 'tags') class VLANTranslationRuleImportForm(NetBoxModelImportForm): @@ -546,7 +544,7 @@ class VLANTranslationRuleImportForm(NetBoxModelImportForm): fields = ('policy', 'local_vid', 'remote_vid') -class ServiceTemplateImportForm(NetBoxModelImportForm): +class ServiceTemplateImportForm(PrimaryModelBulkImportForm): protocol = CSVChoiceField( label=_('Protocol'), choices=ServiceProtocolChoices, @@ -555,10 +553,10 @@ class ServiceTemplateImportForm(NetBoxModelImportForm): class Meta: model = ServiceTemplate - fields = ('name', 'protocol', 'ports', 'description', 'comments', 'tags') + fields = ('name', 'protocol', 'ports', 'description', 'owner', 'comments', 'tags') -class ServiceImportForm(NetBoxModelImportForm): +class ServiceImportForm(PrimaryModelBulkImportForm): parent_object_type = CSVContentTypeField( queryset=ContentType.objects.filter(SERVICE_ASSIGNMENT_MODELS), required=True, @@ -590,7 +588,7 @@ class ServiceImportForm(NetBoxModelImportForm): class Meta: model = Service fields = ( - 'ipaddresses', 'name', 'protocol', 'ports', 'description', 'comments', 'tags', + 'ipaddresses', 'name', 'protocol', 'ports', 'description', 'owner', 'comments', 'tags', ) def __init__(self, data=None, *args, **kwargs): diff --git a/netbox/netbox/forms/bulk_import.py b/netbox/netbox/forms/bulk_import.py index 3504844de..062a8e788 100644 --- a/netbox/netbox/forms/bulk_import.py +++ b/netbox/netbox/forms/bulk_import.py @@ -1,14 +1,19 @@ +from django import forms from django.utils.translation import gettext_lazy as _ from extras.choices import * from extras.models import CustomField, Tag from users.models import Owner from utilities.forms import CSVModelForm -from utilities.forms.fields import CSVModelMultipleChoiceField, CSVModelChoiceField +from utilities.forms.fields import CSVModelMultipleChoiceField, CSVModelChoiceField, SlugField from .model_forms import NetBoxModelForm __all__ = ( + 'NestedGroupModelBulkImportForm', 'NetBoxModelImportForm', + 'OrganizationalModelBulkImportForm', + 'OwnerCSVMixin', + 'PrimaryModelBulkImportForm' ) @@ -16,12 +21,6 @@ class NetBoxModelImportForm(CSVModelForm, NetBoxModelForm): """ Base form for creating NetBox objects from CSV data. Used for bulk importing. """ - owner = CSVModelChoiceField( - queryset=Owner.objects.all(), - required=False, - to_field_name='name', - help_text=_("Name of the object's owner") - ) tags = CSVModelMultipleChoiceField( label=_('Tags'), queryset=Tag.objects.all(), @@ -38,3 +37,33 @@ class NetBoxModelImportForm(CSVModelForm, NetBoxModelForm): def _get_form_field(self, customfield): return customfield.to_form_field(for_csv_import=True) + + +class OwnerCSVMixin(forms.Form): + owner = CSVModelChoiceField( + queryset=Owner.objects.all(), + required=False, + to_field_name='name', + help_text=_("Name of the object's owner") + ) + + +class PrimaryModelBulkImportForm(OwnerCSVMixin, NetBoxModelImportForm): + """ + Bulk import form for models which inherit from PrimaryModel. + """ + pass + + +class OrganizationalModelBulkImportForm(OwnerCSVMixin, NetBoxModelImportForm): + """ + Bulk import form for models which inherit from OrganizationalModel. + """ + slug = SlugField() + + +class NestedGroupModelBulkImportForm(OwnerCSVMixin, NetBoxModelImportForm): + """ + Bulk import form for models which inherit from NestedGroupModel. + """ + slug = SlugField() diff --git a/netbox/tenancy/forms/bulk_import.py b/netbox/tenancy/forms/bulk_import.py index 5861c976b..81729dc7b 100644 --- a/netbox/tenancy/forms/bulk_import.py +++ b/netbox/tenancy/forms/bulk_import.py @@ -2,7 +2,10 @@ from django import forms from django.contrib.contenttypes.models import ContentType from django.utils.translation import gettext_lazy as _ -from netbox.forms import NetBoxModelImportForm +from netbox.forms import ( + NestedGroupModelBulkImportForm, NetBoxModelImportForm, OrganizationalModelBulkImportForm, + PrimaryModelBulkImportForm, +) from tenancy.models import * from utilities.forms.fields import CSVContentTypeField, CSVModelChoiceField, CSVModelMultipleChoiceField, SlugField @@ -20,7 +23,7 @@ __all__ = ( # Tenants # -class TenantGroupImportForm(NetBoxModelImportForm): +class TenantGroupImportForm(NestedGroupModelBulkImportForm): parent = CSVModelChoiceField( label=_('Parent'), queryset=TenantGroup.objects.all(), @@ -28,14 +31,13 @@ class TenantGroupImportForm(NetBoxModelImportForm): to_field_name='name', help_text=_('Parent group'), ) - slug = SlugField() class Meta: model = TenantGroup - fields = ('name', 'slug', 'parent', 'description', 'tags', 'comments') + fields = ('name', 'slug', 'parent', 'description', 'owner', 'comments', 'tags') -class TenantImportForm(NetBoxModelImportForm): +class TenantImportForm(PrimaryModelBulkImportForm): slug = SlugField() group = CSVModelChoiceField( label=_('Group'), @@ -47,14 +49,14 @@ class TenantImportForm(NetBoxModelImportForm): class Meta: model = Tenant - fields = ('name', 'slug', 'group', 'description', 'comments', 'tags') + fields = ('name', 'slug', 'group', 'description', 'owner', 'comments', 'tags') # # Contacts # -class ContactGroupImportForm(NetBoxModelImportForm): +class ContactGroupImportForm(NestedGroupModelBulkImportForm): parent = CSVModelChoiceField( label=_('Parent'), queryset=ContactGroup.objects.all(), @@ -62,22 +64,20 @@ class ContactGroupImportForm(NetBoxModelImportForm): to_field_name='name', help_text=_('Parent group'), ) - slug = SlugField() class Meta: model = ContactGroup - fields = ('name', 'slug', 'parent', 'description', 'tags', 'comments') + fields = ('name', 'slug', 'parent', 'description', 'owner', 'comments', 'tags') -class ContactRoleImportForm(NetBoxModelImportForm): - slug = SlugField() +class ContactRoleImportForm(OrganizationalModelBulkImportForm): class Meta: model = ContactRole - fields = ('name', 'slug', 'description') + fields = ('name', 'slug', 'description', 'owner', 'tags') -class ContactImportForm(NetBoxModelImportForm): +class ContactImportForm(PrimaryModelBulkImportForm): groups = CSVModelMultipleChoiceField( queryset=ContactGroup.objects.all(), required=False, @@ -92,7 +92,9 @@ class ContactImportForm(NetBoxModelImportForm): class Meta: model = Contact - fields = ('name', 'title', 'phone', 'email', 'address', 'link', 'groups', 'description', 'comments', 'tags') + fields = ( + 'name', 'title', 'phone', 'email', 'address', 'link', 'groups', 'description', 'owner', 'comments', 'tags', + ) class ContactAssignmentImportForm(NetBoxModelImportForm): diff --git a/netbox/virtualization/forms/bulk_import.py b/netbox/virtualization/forms/bulk_import.py index 6b5b62d11..c058454b5 100644 --- a/netbox/virtualization/forms/bulk_import.py +++ b/netbox/virtualization/forms/bulk_import.py @@ -5,9 +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 +from netbox.forms import NetBoxModelImportForm, OrganizationalModelBulkImportForm, PrimaryModelBulkImportForm from tenancy.models import Tenant -from utilities.forms.fields import CSVChoiceField, CSVModelChoiceField, SlugField +from utilities.forms.fields import CSVChoiceField, CSVModelChoiceField from virtualization.choices import * from virtualization.models import * @@ -21,23 +21,21 @@ __all__ = ( ) -class ClusterTypeImportForm(NetBoxModelImportForm): - slug = SlugField() +class ClusterTypeImportForm(OrganizationalModelBulkImportForm): class Meta: model = ClusterType - fields = ('name', 'slug', 'description', 'tags') + fields = ('name', 'slug', 'description', 'owner', 'tags') -class ClusterGroupImportForm(NetBoxModelImportForm): - slug = SlugField() +class ClusterGroupImportForm(OrganizationalModelBulkImportForm): class Meta: model = ClusterGroup - fields = ('name', 'slug', 'description', 'tags') + fields = ('name', 'slug', 'description', 'owner', 'tags') -class ClusterImportForm(ScopedImportForm, NetBoxModelImportForm): +class ClusterImportForm(ScopedImportForm, PrimaryModelBulkImportForm): type = CSVModelChoiceField( label=_('Type'), queryset=ClusterType.objects.all(), @@ -74,14 +72,15 @@ class ClusterImportForm(ScopedImportForm, NetBoxModelImportForm): class Meta: model = Cluster fields = ( - 'name', 'type', 'group', 'status', 'scope_type', 'scope_id', 'tenant', 'description', 'comments', 'tags', + 'name', 'type', 'group', 'status', 'scope_type', 'scope_id', 'tenant', 'description', 'owner', 'comments', + 'tags', ) labels = { 'scope_id': _('Scope ID'), } -class VirtualMachineImportForm(NetBoxModelImportForm): +class VirtualMachineImportForm(PrimaryModelBulkImportForm): status = CSVChoiceField( label=_('Status'), choices=VirtualMachineStatusChoices, @@ -143,7 +142,7 @@ class VirtualMachineImportForm(NetBoxModelImportForm): model = VirtualMachine fields = ( 'name', 'status', 'role', 'site', 'cluster', 'device', 'tenant', 'platform', 'vcpus', 'memory', 'disk', - 'description', 'serial', 'config_template', 'comments', 'tags', + 'description', 'serial', 'config_template', 'comments', 'owner', 'tags', ) diff --git a/netbox/vpn/forms/bulk_import.py b/netbox/vpn/forms/bulk_import.py index 96744887e..795431fda 100644 --- a/netbox/vpn/forms/bulk_import.py +++ b/netbox/vpn/forms/bulk_import.py @@ -3,9 +3,9 @@ from django.utils.translation import gettext_lazy as _ from dcim.models import Device, Interface from ipam.models import IPAddress, VLAN -from netbox.forms import NetBoxModelImportForm +from netbox.forms import NetBoxModelImportForm, OrganizationalModelBulkImportForm, PrimaryModelBulkImportForm from tenancy.models import Tenant -from utilities.forms.fields import CSVChoiceField, CSVModelChoiceField, CSVModelMultipleChoiceField, SlugField +from utilities.forms.fields import CSVChoiceField, CSVModelChoiceField, CSVModelMultipleChoiceField from virtualization.models import VirtualMachine, VMInterface from vpn.choices import * from vpn.models import * @@ -24,15 +24,14 @@ __all__ = ( ) -class TunnelGroupImportForm(NetBoxModelImportForm): - slug = SlugField() +class TunnelGroupImportForm(OrganizationalModelBulkImportForm): class Meta: model = TunnelGroup - fields = ('name', 'slug', 'description', 'tags') + fields = ('name', 'slug', 'description', 'owner', 'tags') -class TunnelImportForm(NetBoxModelImportForm): +class TunnelImportForm(PrimaryModelBulkImportForm): status = CSVChoiceField( label=_('Status'), choices=TunnelStatusChoices, @@ -67,7 +66,7 @@ class TunnelImportForm(NetBoxModelImportForm): model = Tunnel fields = ( 'name', 'status', 'group', 'encapsulation', 'ipsec_profile', 'tenant', 'tunnel_id', 'description', - 'comments', 'tags', + 'owner', 'comments', 'tags', ) @@ -140,7 +139,7 @@ class TunnelTerminationImportForm(NetBoxModelImportForm): return super().save(*args, **kwargs) -class IKEProposalImportForm(NetBoxModelImportForm): +class IKEProposalImportForm(PrimaryModelBulkImportForm): authentication_method = CSVChoiceField( label=_('Authentication method'), choices=AuthenticationMethodChoices @@ -163,11 +162,11 @@ class IKEProposalImportForm(NetBoxModelImportForm): model = IKEProposal fields = ( 'name', 'description', 'authentication_method', 'encryption_algorithm', 'authentication_algorithm', - 'group', 'sa_lifetime', 'comments', 'tags', + 'group', 'sa_lifetime', 'owner', 'comments', 'tags', ) -class IKEPolicyImportForm(NetBoxModelImportForm): +class IKEPolicyImportForm(PrimaryModelBulkImportForm): version = CSVChoiceField( label=_('Version'), choices=IKEVersionChoices @@ -186,11 +185,11 @@ class IKEPolicyImportForm(NetBoxModelImportForm): class Meta: model = IKEPolicy fields = ( - 'name', 'description', 'version', 'mode', 'proposals', 'preshared_key', 'comments', 'tags', + 'name', 'description', 'version', 'mode', 'proposals', 'preshared_key', 'owner', 'comments', 'tags', ) -class IPSecProposalImportForm(NetBoxModelImportForm): +class IPSecProposalImportForm(PrimaryModelBulkImportForm): encryption_algorithm = CSVChoiceField( label=_('Encryption algorithm'), choices=EncryptionAlgorithmChoices, @@ -206,11 +205,11 @@ class IPSecProposalImportForm(NetBoxModelImportForm): model = IPSecProposal fields = ( 'name', 'description', 'encryption_algorithm', 'authentication_algorithm', 'sa_lifetime_seconds', - 'sa_lifetime_data', 'comments', 'tags', + 'sa_lifetime_data', 'owner', 'comments', 'tags', ) -class IPSecPolicyImportForm(NetBoxModelImportForm): +class IPSecPolicyImportForm(PrimaryModelBulkImportForm): pfs_group = CSVChoiceField( label=_('Diffie-Hellman group for Perfect Forward Secrecy'), choices=DHGroupChoices, @@ -225,11 +224,11 @@ class IPSecPolicyImportForm(NetBoxModelImportForm): class Meta: model = IPSecPolicy fields = ( - 'name', 'description', 'proposals', 'pfs_group', 'comments', 'tags', + 'name', 'description', 'proposals', 'pfs_group', 'owner', 'comments', 'tags', ) -class IPSecProfileImportForm(NetBoxModelImportForm): +class IPSecProfileImportForm(PrimaryModelBulkImportForm): mode = CSVChoiceField( label=_('Mode'), choices=IPSecModeChoices, @@ -249,11 +248,11 @@ class IPSecProfileImportForm(NetBoxModelImportForm): class Meta: model = IPSecProfile fields = ( - 'name', 'mode', 'ike_policy', 'ipsec_policy', 'description', 'comments', 'tags', + 'name', 'mode', 'ike_policy', 'ipsec_policy', 'description', 'owner', 'comments', 'tags', ) -class L2VPNImportForm(NetBoxModelImportForm): +class L2VPNImportForm(PrimaryModelBulkImportForm): tenant = CSVModelChoiceField( label=_('Tenant'), queryset=Tenant.objects.all(), @@ -273,8 +272,9 @@ class L2VPNImportForm(NetBoxModelImportForm): class Meta: model = L2VPN - fields = ('identifier', 'name', 'slug', 'tenant', 'type', 'description', - 'comments', 'tags') + fields = ( + 'identifier', 'name', 'slug', 'tenant', 'type', 'description', 'owner', 'comments', 'tags', + ) class L2VPNTerminationImportForm(NetBoxModelImportForm): diff --git a/netbox/wireless/forms/bulk_import.py b/netbox/wireless/forms/bulk_import.py index 29395f814..a76e12ef6 100644 --- a/netbox/wireless/forms/bulk_import.py +++ b/netbox/wireless/forms/bulk_import.py @@ -5,9 +5,9 @@ from dcim.forms.mixins import ScopedImportForm from dcim.models import Device, Interface, Site from ipam.models import VLAN from netbox.choices import * -from netbox.forms import NetBoxModelImportForm +from netbox.forms import NestedGroupModelBulkImportForm, PrimaryModelBulkImportForm from tenancy.models import Tenant -from utilities.forms.fields import CSVChoiceField, CSVModelChoiceField, SlugField +from utilities.forms.fields import CSVChoiceField, CSVModelChoiceField from wireless.choices import * from wireless.models import * @@ -18,7 +18,7 @@ __all__ = ( ) -class WirelessLANGroupImportForm(NetBoxModelImportForm): +class WirelessLANGroupImportForm(NestedGroupModelBulkImportForm): parent = CSVModelChoiceField( label=_('Parent'), queryset=WirelessLANGroup.objects.all(), @@ -26,14 +26,13 @@ class WirelessLANGroupImportForm(NetBoxModelImportForm): to_field_name='name', help_text=_('Parent group') ) - slug = SlugField() class Meta: model = WirelessLANGroup - fields = ('name', 'slug', 'parent', 'description', 'tags', 'comments') + fields = ('name', 'slug', 'parent', 'description', 'owner', 'comments', 'tags') -class WirelessLANImportForm(ScopedImportForm, NetBoxModelImportForm): +class WirelessLANImportForm(ScopedImportForm, PrimaryModelBulkImportForm): group = CSVModelChoiceField( label=_('Group'), queryset=WirelessLANGroup.objects.all(), @@ -77,14 +76,14 @@ class WirelessLANImportForm(ScopedImportForm, NetBoxModelImportForm): model = WirelessLAN fields = ( 'ssid', 'group', 'status', 'vlan', 'tenant', 'auth_type', 'auth_cipher', 'auth_psk', 'scope_type', - 'scope_id', 'description', 'comments', 'tags', + 'scope_id', 'description', 'owner', 'comments', 'tags', ) labels = { 'scope_id': _('Scope ID'), } -class WirelessLinkImportForm(NetBoxModelImportForm): +class WirelessLinkImportForm(PrimaryModelBulkImportForm): # Termination A site_a = CSVModelChoiceField( label=_('Site A'), @@ -163,7 +162,8 @@ class WirelessLinkImportForm(NetBoxModelImportForm): model = WirelessLink fields = ( 'site_a', 'device_a', 'interface_a', 'site_b', 'device_b', 'interface_b', 'status', 'ssid', 'tenant', - 'auth_type', 'auth_cipher', 'auth_psk', 'distance', 'distance_unit', 'description', 'comments', 'tags', + 'auth_type', 'auth_cipher', 'auth_psk', 'distance', 'distance_unit', 'description', 'owner', 'comments', + 'tags', ) def __init__(self, data=None, *args, **kwargs):