diff --git a/netbox/dcim/forms/bulk_edit.py b/netbox/dcim/forms/bulk_edit.py index b2733b60ca0..e9a86cc4aa4 100644 --- a/netbox/dcim/forms/bulk_edit.py +++ b/netbox/dcim/forms/bulk_edit.py @@ -359,6 +359,11 @@ class RackBulkEditForm(NetBoxModelBulkEditForm): queryset=RackRole.objects.all(), required=False ) + rack_type = DynamicModelChoiceField( + label=_('Rack type'), + queryset=RackType.objects.all(), + required=False, + ) serial = forms.CharField( max_length=50, required=False, @@ -438,7 +443,7 @@ class RackBulkEditForm(NetBoxModelBulkEditForm): model = Rack fieldsets = ( - FieldSet('status', 'role', 'tenant', 'serial', 'asset_tag', 'description', name=_('Rack')), + FieldSet('status', 'role', 'tenant', 'serial', 'asset_tag', 'rack_type', 'description', name=_('Rack')), FieldSet('region', 'site_group', 'site', 'location', name=_('Location')), FieldSet( 'form_factor', 'width', 'u_height', 'desc_units', 'airflow', 'outer_width', 'outer_depth', 'outer_unit', diff --git a/netbox/dcim/forms/bulk_import.py b/netbox/dcim/forms/bulk_import.py index 58ae350913f..76fae478b31 100644 --- a/netbox/dcim/forms/bulk_import.py +++ b/netbox/dcim/forms/bulk_import.py @@ -256,6 +256,13 @@ class RackImportForm(NetBoxModelImportForm): to_field_name='name', help_text=_('Name of assigned role') ) + rack_type = CSVModelChoiceField( + label=_('Rack type'), + queryset=RackType.objects.all(), + to_field_name='model', + required=False, + help_text=_('Rack type model') + ) form_factor = CSVChoiceField( label=_('Type'), choices=RackFormFactorChoices, @@ -265,8 +272,13 @@ class RackImportForm(NetBoxModelImportForm): width = forms.ChoiceField( label=_('Width'), choices=RackWidthChoices, + required=False, help_text=_('Rail-to-rail width (in inches)') ) + u_height = forms.IntegerField( + required=False, + label=_('Height (U)') + ) outer_unit = CSVChoiceField( label=_('Outer unit'), choices=RackDimensionUnitChoices, @@ -289,9 +301,9 @@ class RackImportForm(NetBoxModelImportForm): class Meta: model = Rack fields = ( - 'site', 'location', 'name', 'facility_id', 'tenant', 'status', 'role', 'form_factor', 'serial', 'asset_tag', - 'width', 'u_height', 'desc_units', 'outer_width', 'outer_depth', 'outer_unit', 'mounting_depth', 'airflow', - 'weight', 'max_weight', 'weight_unit', 'description', 'comments', 'tags', + 'site', 'location', 'name', 'facility_id', 'tenant', 'status', 'role', 'rack_type', 'form_factor', 'serial', + 'asset_tag', 'width', 'u_height', 'desc_units', 'outer_width', 'outer_depth', 'outer_unit', + 'mounting_depth', 'airflow', 'weight', 'max_weight', 'weight_unit', 'description', 'comments', 'tags', ) def __init__(self, data=None, *args, **kwargs): @@ -303,6 +315,16 @@ def __init__(self, data=None, *args, **kwargs): params = {f"site__{self.fields['site'].to_field_name}": data.get('site')} self.fields['location'].queryset = self.fields['location'].queryset.filter(**params) + def clean(self): + super().clean() + + # width & u_height must be set if not specifying a rack type on import + if not self.instance.pk: + if not self.cleaned_data.get('rack_type') and not self.cleaned_data.get('width'): + raise forms.ValidationError(_("Width must be set if not specifying a rack type.")) + if not self.cleaned_data.get('rack_type') and not self.cleaned_data.get('u_height'): + raise forms.ValidationError(_("U height must be set if not specifying a rack type.")) + class RackReservationImportForm(NetBoxModelImportForm): site = CSVModelChoiceField(