From a1ff3800c7491a652e39c6529becae41162267bd Mon Sep 17 00:00:00 2001 From: kkthxbye-code <> Date: Wed, 8 Feb 2023 12:08:00 +0100 Subject: [PATCH 1/2] Fixes #11032 - Replication fields broken in custom validation --- netbox/netbox/models/features.py | 4 ++++ netbox/netbox/views/generic/object_views.py | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/netbox/netbox/models/features.py b/netbox/netbox/models/features.py index 8e5af0ab58b..4866eeb373e 100644 --- a/netbox/netbox/models/features.py +++ b/netbox/netbox/models/features.py @@ -257,6 +257,10 @@ class Meta: def clean(self): super().clean() + # If the instance is a base for replications, skip custom validation + if hasattr(self, '_replicated_base'): + return + # Send the post_clean signal post_clean.send(sender=self.__class__, instance=self) diff --git a/netbox/netbox/views/generic/object_views.py b/netbox/netbox/views/generic/object_views.py index d855490d18c..475cca9d30a 100644 --- a/netbox/netbox/views/generic/object_views.py +++ b/netbox/netbox/views/generic/object_views.py @@ -436,6 +436,10 @@ def post(self, request): form = self.initialize_form(request) instance = self.alter_object(self.queryset.model(), request) + # Note that the form instance is a replicated field base + # This is needed to avoid running custom validators multiple times + form.instance._replicated_base = hasattr(self.form, "replication_fields") + if form.is_valid(): new_components = [] data = deepcopy(request.POST) From a4700bc498398d87e614eaf68a27f625f75802b5 Mon Sep 17 00:00:00 2001 From: kkthxbye-code <> Date: Wed, 8 Feb 2023 12:18:06 +0100 Subject: [PATCH 2/2] Use getattr instead of hasattr to make sure custom validation is triggered as normal --- netbox/netbox/models/features.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/netbox/models/features.py b/netbox/netbox/models/features.py index 4866eeb373e..f041d016d09 100644 --- a/netbox/netbox/models/features.py +++ b/netbox/netbox/models/features.py @@ -258,7 +258,7 @@ def clean(self): super().clean() # If the instance is a base for replications, skip custom validation - if hasattr(self, '_replicated_base'): + if getattr(self, '_replicated_base', False): return # Send the post_clean signal