Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

14042 mptt cache count #14048

Merged
merged 3 commits into from
Oct 17, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion netbox/utilities/counters.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ def post_delete_receiver(sender, instance, **kwargs):

# Decrement the parent's counter by one
if parent_pk is not None:
update_counter(parent_model, parent_pk, counter_name, -1)
# MPTT sends two delete signals if child element so guard against multiple decrements
origin = kwargs.get('origin')
jeremystretch marked this conversation as resolved.
Show resolved Hide resolved
if not origin or origin == instance:
update_counter(parent_model, parent_pk, counter_name, -1)


#
Expand Down
39 changes: 36 additions & 3 deletions netbox/utilities/tests/test_counters.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
from django.test import TestCase
from django.contrib.contenttypes.models import ContentType
from django.test import override_settings
from django.urls import reverse

from dcim.models import *
from utilities.testing.utils import create_test_device
from users.models import ObjectPermission
from utilities.testing.base import TestCase
from utilities.testing.utils import create_test_device, create_test_user


class CountersTest(TestCase):
Expand All @@ -10,7 +14,6 @@ class CountersTest(TestCase):
"""
@classmethod
def setUpTestData(cls):

# Create devices
device1 = create_test_device('Device 1')
device2 = create_test_device('Device 2')
Expand Down Expand Up @@ -79,3 +82,33 @@ def test_interface_count_move(self):
device2.refresh_from_db()
self.assertEqual(device1.interface_count, 1)
self.assertEqual(device2.interface_count, 3)

@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_mptt_child_delete(self):
device1, device2 = Device.objects.all()
inventory_item1 = InventoryItem.objects.create(device=device1, name='Inventory Item 1')
inventory_item2 = InventoryItem.objects.create(device=device1, name='Inventory Item 1', parent=inventory_item1)
jeremystretch marked this conversation as resolved.
Show resolved Hide resolved
device1.refresh_from_db()
self.assertEqual(device1.inventory_item_count, 2)

# Setup bulk_delete for the inventory items
pk_list = device1.inventoryitems.values_list('pk', flat=True)
data = {
'pk': pk_list,
'confirm': True,
'_confirm': True, # Form button
}

# Assign unconstrained permission
obj_perm = ObjectPermission(
name='Test permission',
actions=['delete']
)
obj_perm.save()
obj_perm.users.add(self.user.pk)
obj_perm.object_types.add(ContentType.objects.get_for_model(InventoryItem))
jeremystretch marked this conversation as resolved.
Show resolved Hide resolved

# Try POST with model-level permission
self.client.post(reverse("dcim:inventoryitem_bulk_delete"), data)
device1.refresh_from_db()
self.assertEqual(device1.inventory_item_count, 0)