Skip to content

Commit f052361

Browse files
authored
Fixes #20542: Add form prefix to POST handler in ObjectEditView (#20550)
Commit d222466 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.
1 parent 7719b98 commit f052361

File tree

2 files changed

+30
-2
lines changed

2 files changed

+30
-2
lines changed

netbox/dcim/tests/test_views.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@
77
from django.urls import reverse
88
from netaddr import EUI
99

10+
from core.models import ObjectType
1011
from dcim.choices import *
1112
from dcim.constants import *
1213
from dcim.models import *
1314
from ipam.models import ASN, RIR, VLAN, VRF
1415
from netbox.choices import CSVDelimiterChoices, ImportFormatChoices, WeightUnitChoices
1516
from tenancy.models import Tenant
16-
from users.models import User
17+
from users.models import ObjectPermission, User
1718
from utilities.testing import ViewTestCases, create_tags, create_test_device, post_data
1819
from wireless.models import WirelessLAN
1920

@@ -3728,3 +3729,29 @@ def setUpTestData(cls):
37283729
cls.bulk_edit_data = {
37293730
'description': 'New description',
37303731
}
3732+
3733+
@tag('regression') # Issue #20542
3734+
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'], EXEMPT_EXCLUDE_MODELS=[])
3735+
def test_create_macaddress_via_quickadd(self):
3736+
"""
3737+
Test creating a MAC address via quick-add modal (e.g., from Interface form).
3738+
Regression test for issue #20542 where form prefix was missing in POST handler.
3739+
"""
3740+
obj_perm = ObjectPermission(name='Test permission', actions=['add'])
3741+
obj_perm.save()
3742+
obj_perm.users.add(self.user)
3743+
obj_perm.object_types.add(ObjectType.objects.get_for_model(self.model))
3744+
3745+
# Simulate quick-add form submission with 'quickadd-' prefix
3746+
formatted_data = post_data(self.form_data)
3747+
quickadd_data = {f'quickadd-{k}': v for k, v in formatted_data.items()}
3748+
quickadd_data['_quickadd'] = 'True'
3749+
3750+
initial_count = self._get_queryset().count()
3751+
url = f"{self._get_url('add')}?_quickadd=True&target=id_primary_mac_address"
3752+
response = self.client.post(url, data=quickadd_data)
3753+
3754+
# Should successfully create the MAC address and return the quick_add_created template
3755+
self.assertHttpStatus(response, 200)
3756+
self.assertIn(b'quick-add-object', response.content)
3757+
self.assertEqual(initial_count + 1, self._get_queryset().count())

netbox/netbox/views/generic/object_views.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,8 @@ def post(self, request, *args, **kwargs):
281281

282282
obj = self.alter_object(obj, request, args, kwargs)
283283

284-
form = self.form(data=request.POST, files=request.FILES, instance=obj)
284+
form_prefix = 'quickadd' if request.GET.get('_quickadd') else None
285+
form = self.form(data=request.POST, files=request.FILES, instance=obj, prefix=form_prefix)
285286
restrict_form_fields(form, request.user)
286287

287288
if form.is_valid():

0 commit comments

Comments
 (0)