Skip to content

Commit b937358

Browse files
Fixes #14081: Fix cached counters on delete for parent-child items (#14131)
* 14081 fixed cached counters on delete for parent-child items * Misc cleanup --------- Co-authored-by: Jeremy Stretch <[email protected]>
1 parent 6939ae4 commit b937358

File tree

1 file changed

+15
-5
lines changed

1 file changed

+15
-5
lines changed

netbox/utilities/counters.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from django.apps import apps
22
from django.db.models import F, Count, OuterRef, Subquery
3-
from django.db.models.signals import post_delete, post_save
3+
from django.db.models.signals import post_delete, post_save, pre_delete
44

55
from netbox.registry import registry
66
from .fields import CounterCacheField
@@ -62,6 +62,12 @@ def post_save_receiver(sender, instance, created, **kwargs):
6262
update_counter(parent_model, new_pk, counter_name, 1)
6363

6464

65+
def pre_delete_receiver(sender, instance, origin, **kwargs):
66+
model = instance._meta.model
67+
if not model.objects.filter(pk=instance.pk).exists():
68+
instance._previously_removed = True
69+
70+
6571
def post_delete_receiver(sender, instance, origin, **kwargs):
6672
"""
6773
Update counter fields on related objects when a TrackingModelMixin subclass is deleted.
@@ -71,10 +77,8 @@ def post_delete_receiver(sender, instance, origin, **kwargs):
7177
parent_pk = getattr(instance, field_name, None)
7278

7379
# Decrement the parent's counter by one
74-
if parent_pk is not None:
75-
# MPTT sends two delete signals for child elements so guard against multiple decrements
76-
if not origin or origin == instance:
77-
update_counter(parent_model, parent_pk, counter_name, -1)
80+
if parent_pk is not None and not hasattr(instance, "_previously_removed"):
81+
update_counter(parent_model, parent_pk, counter_name, -1)
7882

7983

8084
#
@@ -106,6 +110,12 @@ def connect_counters(*models):
106110
weak=False,
107111
dispatch_uid=f'{model._meta.label}.{field.name}'
108112
)
113+
pre_delete.connect(
114+
pre_delete_receiver,
115+
sender=to_model,
116+
weak=False,
117+
dispatch_uid=f'{model._meta.label}.{field.name}'
118+
)
109119
post_delete.connect(
110120
post_delete_receiver,
111121
sender=to_model,

0 commit comments

Comments
 (0)