From f0523611d1c5e25174a2f68bebe3609fd9d60f1e Mon Sep 17 00:00:00 2001 From: Jason Novinger Date: Thu, 9 Oct 2025 16:42:59 -0500 Subject: [PATCH] Fixes #20542: Add form prefix to `POST` handler in `ObjectEditView` (#20550) Commit d22246688 added form prefix support to the `GET` handler to fix Markdown preview functionality in quick add modals. The form prefix allows Django to properly namespace field names and IDs when rendering forms within the quick add modal context. However, the corresponding change was not made to the `POST` handler. This created a mismatch where form fields were rendered with the `quickadd-` prefix during `GET` requests, but the `POST` handler instantiated forms without the prefix. When users submitted quick add forms, Django looked for unprefixed field names like `address` and `status` in the `POST` data, but the actual submitted data used prefixed names like `quickadd-address` and `quickadd-status`. This caused validation to fail immediately with "This field is required" errors for all required fields, making every quick add form unusable. The fix adds the same prefix detection logic to the `POST` handler that was added to the `GET` handler, checking for the `_quickadd` parameter in the query string and applying the `quickadd` prefix when present. This ensures consistent form field naming between rendering and validation. A regression test has been added to `MACAddressTestCase` to verify that MAC addresses can be successfully created via the quick add modal, preventing this issue from recurring. This test should be promoted to a template test whenever it becomes possible to determine if a model should support quick-add functionality. --- netbox/dcim/tests/test_views.py | 29 ++++++++++++++++++++- netbox/netbox/views/generic/object_views.py | 3 ++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/netbox/dcim/tests/test_views.py b/netbox/dcim/tests/test_views.py index 2e6d5ebc5..91453b446 100644 --- a/netbox/dcim/tests/test_views.py +++ b/netbox/dcim/tests/test_views.py @@ -7,13 +7,14 @@ from django.test import override_settings, tag from django.urls import reverse from netaddr import EUI +from core.models import ObjectType from dcim.choices import * from dcim.constants import * from dcim.models import * from ipam.models import ASN, RIR, VLAN, VRF from netbox.choices import CSVDelimiterChoices, ImportFormatChoices, WeightUnitChoices from tenancy.models import Tenant -from users.models import User +from users.models import ObjectPermission, User from utilities.testing import ViewTestCases, create_tags, create_test_device, post_data from wireless.models import WirelessLAN @@ -3728,3 +3729,29 @@ class MACAddressTestCase(ViewTestCases.PrimaryObjectViewTestCase): cls.bulk_edit_data = { 'description': 'New description', } + + @tag('regression') # Issue #20542 + @override_settings(EXEMPT_VIEW_PERMISSIONS=['*'], EXEMPT_EXCLUDE_MODELS=[]) + def test_create_macaddress_via_quickadd(self): + """ + Test creating a MAC address via quick-add modal (e.g., from Interface form). + Regression test for issue #20542 where form prefix was missing in POST handler. + """ + obj_perm = ObjectPermission(name='Test permission', actions=['add']) + obj_perm.save() + obj_perm.users.add(self.user) + obj_perm.object_types.add(ObjectType.objects.get_for_model(self.model)) + + # Simulate quick-add form submission with 'quickadd-' prefix + formatted_data = post_data(self.form_data) + quickadd_data = {f'quickadd-{k}': v for k, v in formatted_data.items()} + quickadd_data['_quickadd'] = 'True' + + initial_count = self._get_queryset().count() + url = f"{self._get_url('add')}?_quickadd=True&target=id_primary_mac_address" + response = self.client.post(url, data=quickadd_data) + + # Should successfully create the MAC address and return the quick_add_created template + self.assertHttpStatus(response, 200) + self.assertIn(b'quick-add-object', response.content) + self.assertEqual(initial_count + 1, self._get_queryset().count()) diff --git a/netbox/netbox/views/generic/object_views.py b/netbox/netbox/views/generic/object_views.py index 4e8c3ad86..897191592 100644 --- a/netbox/netbox/views/generic/object_views.py +++ b/netbox/netbox/views/generic/object_views.py @@ -281,7 +281,8 @@ class ObjectEditView(GetReturnURLMixin, BaseObjectView): obj = self.alter_object(obj, request, args, kwargs) - form = self.form(data=request.POST, files=request.FILES, instance=obj) + form_prefix = 'quickadd' if request.GET.get('_quickadd') else None + form = self.form(data=request.POST, files=request.FILES, instance=obj, prefix=form_prefix) restrict_form_fields(form, request.user) if form.is_valid():