diff --git a/netbox/netbox/forms/base.py b/netbox/netbox/forms/base.py index 9cd6bbd47..723ae00e2 100644 --- a/netbox/netbox/forms/base.py +++ b/netbox/netbox/forms/base.py @@ -71,6 +71,10 @@ class NetBoxModelBulkEditForm(BootstrapMixin, CustomFieldsMixin, forms.Form): """ nullable_fields = () + pk = forms.ModelMultipleChoiceField( + queryset=None, + widget=forms.MultipleHiddenInput + ) add_tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), required=False @@ -80,6 +84,10 @@ class NetBoxModelBulkEditForm(BootstrapMixin, CustomFieldsMixin, forms.Form): required=False ) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.fields['pk'].queryset = self.model.objects.all() + def _get_form_field(self, customfield): return customfield.to_form_field(set_initial=False, enforce_required=False) @@ -89,18 +97,19 @@ class NetBoxModelBulkEditForm(BootstrapMixin, CustomFieldsMixin, forms.Form): """ nullable_custom_fields = [] for customfield in self._get_custom_fields(self._get_content_type()): + field_name = f'cf_{customfield.name}' + self.fields[field_name] = self._get_form_field(customfield) + # Record non-required custom fields as nullable if not customfield.required: - nullable_custom_fields.append(customfield.name) - - self.fields[customfield.name] = self._get_form_field(customfield) + nullable_custom_fields.append(field_name) # Annotate the field in the list of CustomField form fields - self.custom_fields[customfield.name] = customfield + self.custom_fields[field_name] = customfield # Annotate nullable custom fields (if any) on the form instance if nullable_custom_fields: - self.custom_fields = (*self.custom_fields, *nullable_custom_fields) + self.nullable_fields = (*self.nullable_fields, *nullable_custom_fields) class NetBoxModelFilterSetForm(BootstrapMixin, CustomFieldsMixin, forms.Form): diff --git a/netbox/netbox/views/generic/bulk_views.py b/netbox/netbox/views/generic/bulk_views.py index 3db44ec91..a3e9b48c1 100644 --- a/netbox/netbox/views/generic/bulk_views.py +++ b/netbox/netbox/views/generic/bulk_views.py @@ -481,10 +481,12 @@ class BulkEditView(GetReturnURLMixin, BaseMultiObjectView): # Update custom fields for name in custom_fields: + assert name.startswith('cf_') + cf_name = name[3:] # Strip cf_ prefix if name in form.nullable_fields and name in nullified_fields: - obj.custom_field_data[name] = None + obj.custom_field_data[cf_name] = None elif name in form.changed_data: - obj.custom_field_data[name] = form.fields[name].prepare_value(form.cleaned_data[name]) + obj.custom_field_data[cf_name] = form.fields[name].prepare_value(form.cleaned_data[name]) obj.full_clean() obj.save() diff --git a/netbox/tenancy/forms/bulk_edit.py b/netbox/tenancy/forms/bulk_edit.py index c6d0be882..9de4969fb 100644 --- a/netbox/tenancy/forms/bulk_edit.py +++ b/netbox/tenancy/forms/bulk_edit.py @@ -36,10 +36,10 @@ class TenantGroupBulkEditForm(NetBoxModelBulkEditForm): class TenantBulkEditForm(NetBoxModelBulkEditForm): - pk = forms.ModelMultipleChoiceField( - queryset=Tenant.objects.all(), - widget=forms.MultipleHiddenInput() - ) + # pk = forms.ModelMultipleChoiceField( + # queryset=Tenant.objects.all(), + # widget=forms.MultipleHiddenInput() + # ) group = DynamicModelChoiceField( queryset=TenantGroup.objects.all(), required=False