Skip to content

Commit bee004f

Browse files
authored
Fixes: #18717 - On delete signal handling, manually save the related object in a ManyToOneRel to trigger a change record (#19308)
* On delete signal handling, manually save the related object in a ManyToOneRel to trigger a change record * Only set remote field to None if null=True on the relation
1 parent e1b2b4b commit bee004f

File tree

1 file changed

+9
-3
lines changed

1 file changed

+9
-3
lines changed

netbox/core/signals.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from django.contrib.contenttypes.models import ContentType
44
from django.core.exceptions import ValidationError
5-
from django.db.models.fields.reverse_related import ManyToManyRel
5+
from django.db.models.fields.reverse_related import ManyToManyRel, ManyToOneRel
66
from django.db.models.signals import m2m_changed, post_save, pre_delete
77
from django.dispatch import receiver, Signal
88
from django.utils.translation import gettext_lazy as _
@@ -146,8 +146,10 @@ def handle_deleted_object(sender, instance, **kwargs):
146146
# instance being deleted, and explicitly call .remove() on the remote M2M field to delete
147147
# the association. This triggers an m2m_changed signal with the `post_remove` action type
148148
# for the forward direction of the relationship, ensuring that the change is recorded.
149+
# Similarly, for many-to-one relationships, we set the value on the related object to None
150+
# and save it to trigger a change record on that object.
149151
for relation in instance._meta.related_objects:
150-
if type(relation) is not ManyToManyRel:
152+
if type(relation) not in [ManyToManyRel, ManyToOneRel]:
151153
continue
152154
related_model = relation.related_model
153155
related_field_name = relation.remote_field.name
@@ -157,7 +159,11 @@ def handle_deleted_object(sender, instance, **kwargs):
157159
continue
158160
for obj in related_model.objects.filter(**{related_field_name: instance.pk}):
159161
obj.snapshot() # Ensure the change record includes the "before" state
160-
getattr(obj, related_field_name).remove(instance)
162+
if type(relation) is ManyToManyRel:
163+
getattr(obj, related_field_name).remove(instance)
164+
elif type(relation) is ManyToOneRel and relation.field.null is True:
165+
setattr(obj, related_field_name, None)
166+
obj.save()
161167

162168
# Enqueue the object for event processing
163169
queue = events_queue.get()

0 commit comments

Comments
 (0)