11from django .apps import apps
22from 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
55from netbox .registry import registry
66from .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+
6571def 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