From 15541c644099142bf48b5e35051755c084f126d9 Mon Sep 17 00:00:00 2001 From: Daniel Sheppard Date: Tue, 5 Aug 2025 15:26:12 -0500 Subject: [PATCH 1/5] Fixes: #19998 - Add changelog entry when clearing M2M fields --- netbox/core/signals.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/netbox/core/signals.py b/netbox/core/signals.py index 3d0317011f..9f08c4e652 100644 --- a/netbox/core/signals.py +++ b/netbox/core/signals.py @@ -13,6 +13,7 @@ from core.choices import JobStatusChoices, ObjectChangeActionChoices from core.events import * from extras.events import enqueue_event +from extras.models import Tag from extras.utils import run_validators from netbox.config import get_config from netbox.context import current_request, events_queue @@ -72,6 +73,15 @@ def handle_changed_object(sender, instance, **kwargs): # m2m_changed with objects added or removed m2m_changed = True event_type = OBJECT_UPDATED + elif kwargs.get('action') == 'post_clear': + # Handle clearing of an M2M field + if isinstance(Tag, kwargs.get('model')) and getattr(instance, '_prechange_snapshot', {}).get('tags'): + # Handle tags as it is a Generic M2M + m2m_changed = True + event_type = OBJECT_UPDATED + else: + # Other M2M models are unsupported + return else: return From a86cd9dfc6cb10386a3d5a45a33ea2264926cdea Mon Sep 17 00:00:00 2001 From: Daniel Sheppard Date: Tue, 5 Aug 2025 15:49:01 -0500 Subject: [PATCH 2/5] Clarify comment --- netbox/core/signals.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/netbox/core/signals.py b/netbox/core/signals.py index 9f08c4e652..e5342dbf2f 100644 --- a/netbox/core/signals.py +++ b/netbox/core/signals.py @@ -76,7 +76,8 @@ def handle_changed_object(sender, instance, **kwargs): elif kwargs.get('action') == 'post_clear': # Handle clearing of an M2M field if isinstance(Tag, kwargs.get('model')) and getattr(instance, '_prechange_snapshot', {}).get('tags'): - # Handle tags as it is a Generic M2M + # Handle generation of M2M changes for Tags which have a previous value (ignoring changes where the + # prechange snapshot is empty) m2m_changed = True event_type = OBJECT_UPDATED else: From 043275df19cf5267cb901eecdef8752ae7779581 Mon Sep 17 00:00:00 2001 From: Daniel Sheppard Date: Thu, 7 Aug 2025 08:24:54 -0500 Subject: [PATCH 3/5] Clarify label --- netbox/core/signals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/core/signals.py b/netbox/core/signals.py index e5342dbf2f..78e2668667 100644 --- a/netbox/core/signals.py +++ b/netbox/core/signals.py @@ -81,7 +81,7 @@ def handle_changed_object(sender, instance, **kwargs): m2m_changed = True event_type = OBJECT_UPDATED else: - # Other M2M models are unsupported + # Other endpoints are unimpacted as they send post_add and post_remove return else: return From 630d7aa4c2c6d650ec3046157cb3923519687514 Mon Sep 17 00:00:00 2001 From: Daniel Sheppard Date: Thu, 7 Aug 2025 08:27:13 -0500 Subject: [PATCH 4/5] Clarify additional branch functionality --- netbox/core/signals.py | 1 + 1 file changed, 1 insertion(+) diff --git a/netbox/core/signals.py b/netbox/core/signals.py index 78e2668667..64aff1b65d 100644 --- a/netbox/core/signals.py +++ b/netbox/core/signals.py @@ -82,6 +82,7 @@ def handle_changed_object(sender, instance, **kwargs): event_type = OBJECT_UPDATED else: # Other endpoints are unimpacted as they send post_add and post_remove + # This will impact changes that utilize clear() however so we may want to give consideration for this branch return else: return From 6c0dc8b6302e278104f65766682bc126c025d3df Mon Sep 17 00:00:00 2001 From: Daniel Sheppard Date: Thu, 7 Aug 2025 21:12:25 -0500 Subject: [PATCH 5/5] Correct mistake made on determination of whether it is a tag or not --- netbox/core/signals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/core/signals.py b/netbox/core/signals.py index 64aff1b65d..e042255a74 100644 --- a/netbox/core/signals.py +++ b/netbox/core/signals.py @@ -75,7 +75,7 @@ def handle_changed_object(sender, instance, **kwargs): event_type = OBJECT_UPDATED elif kwargs.get('action') == 'post_clear': # Handle clearing of an M2M field - if isinstance(Tag, kwargs.get('model')) and getattr(instance, '_prechange_snapshot', {}).get('tags'): + if kwargs.get('model') == Tag and getattr(instance, '_prechange_snapshot', {}).get('tags'): # Handle generation of M2M changes for Tags which have a previous value (ignoring changes where the # prechange snapshot is empty) m2m_changed = True