Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
16 changes: 16 additions & 0 deletions netbox/netbox/object_actions.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from django.db.models import ForeignKey
from django.template import loader
from django.urls.exceptions import NoReverseMatch
from django.utils.translation import gettext_lazy as _
Expand Down Expand Up @@ -175,6 +176,21 @@ class BulkEdit(ObjectAction):
permissions_required = {'change'}
template_name = 'buttons/bulk_edit.html'

@classmethod
def get_context(cls, context, model):
url_params = super().get_url_params(context)

# If this is a child object, pass the parent's PK as a URL parameter
if parent := context.get('object'):
for field in model._meta.get_fields():
if isinstance(field, ForeignKey) and field.remote_field.model == parent.__class__:
url_params[field.name] = parent.pk
break

return {
'url_params': url_params,
}


class BulkRename(ObjectAction):
"""
Expand Down
37 changes: 32 additions & 5 deletions netbox/netbox/tests/test_object_actions.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
from unittest import skipIf

from django.conf import settings
from django.test import TestCase
from django.test import RequestFactory, TestCase

from dcim.models import Device
from netbox.object_actions import AddObject, BulkImport
from netbox.tests.dummy_plugin.models import DummyNetBoxModel
from dcim.models import Device, DeviceType, Manufacturer
from netbox.object_actions import AddObject, BulkEdit, BulkImport


class ObjectActionTest(TestCase):
Expand All @@ -20,13 +19,41 @@ def test_get_url_core_model(self):
url = BulkImport.get_url(obj)
self.assertEqual(url, '/dcim/devices/import/')

@skipIf('netbox.tests.dummy_plugin' not in settings.PLUGINS, "dummy_plugin not in settings.PLUGINS")
@skipIf('netbox.tests.dummy_plugin' not in settings.PLUGINS, 'dummy_plugin not in settings.PLUGINS')
def test_get_url_plugin_model(self):
"""Test URL generation for plugin models includes plugins: namespace"""
from netbox.tests.dummy_plugin.models import DummyNetBoxModel

obj = DummyNetBoxModel()

url = AddObject.get_url(obj)
self.assertEqual(url, '/plugins/dummy-plugin/netboxmodel/add/')

url = BulkImport.get_url(obj)
self.assertEqual(url, '/plugins/dummy-plugin/netboxmodel/import/')

def test_bulk_edit_get_context_child_object(self):
"""
Test that the parent object's PK is included in the context for child objects.

Ensure that BulkEdit.get_context() correctly identifies and
includes the parent object's PK when rendering a child object's
action button.
"""
manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')

# Mock context containing the parent object (DeviceType)
request = RequestFactory().get('/')
context = {
'request': request,
'object': device_type,
}

# Get context for the child model (Device)
action_context = BulkEdit.get_context(context, Device)

# Verify that 'device_type' (the FK field name) is present in
# url_params with the parent's PK
self.assertIn('url_params', action_context)
self.assertEqual(action_context['url_params'].get('device_type'), device_type.pk)
Loading