From d592285b98d0092cba581d8cedb0d068569e1a2c Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 15 Dec 2023 13:28:36 -0500 Subject: [PATCH] Enforce custom validators during bulk edit --- netbox/extras/validators.py | 8 +++----- netbox/netbox/views/generic/bulk_views.py | 8 ++++++++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/netbox/extras/validators.py b/netbox/extras/validators.py index 82e11f3f9..e80598044 100644 --- a/netbox/extras/validators.py +++ b/netbox/extras/validators.py @@ -86,14 +86,12 @@ class CustomValidator: if name in m2m_fields: if name in instance._m2m_values: return instance._m2m_values[name] - elif instance.pk: - # TODO: Handle invalid attrs + if instance.pk: return list(getattr(instance, name).all()) - else: - return [] + return [] # Raise a ValidationError for unknown attributes - elif not hasattr(instance, name): + if not hasattr(instance, name): raise ValidationError(_('Invalid attribute "{name}" for {model}').format( name=name, model=instance.__class__.__name__ diff --git a/netbox/netbox/views/generic/bulk_views.py b/netbox/netbox/views/generic/bulk_views.py index c5a08c80a..69bb85c41 100644 --- a/netbox/netbox/views/generic/bulk_views.py +++ b/netbox/netbox/views/generic/bulk_views.py @@ -557,6 +557,14 @@ class BulkEditView(GetReturnURLMixin, BaseMultiObjectView): elif name in form.changed_data: obj.custom_field_data[cf_name] = customfield.serialize(form.cleaned_data[name]) + # Store M2M values for validation + obj._m2m_values = {} + for field in obj._meta.local_many_to_many: + if value := form.cleaned_data.get(field.name): + obj._m2m_values[field.name] = list(value) + elif field.name in nullified_fields: + obj._m2m_values[field.name] = [] + obj.full_clean() obj.save() updated_objects.append(obj)