Skip to content

Commit 828dfb3

Browse files
Srinath0916pandafynemesifier
authored
[fix] Fixed MultiValueDictKeyError on empty device form submission #1057
Fixes #1057 --------- Co-authored-by: Gagan Deep <[email protected]> Co-authored-by: Federico Capoano <[email protected]>
1 parent 03ddc6c commit 828dfb3

File tree

2 files changed

+42
-3
lines changed

2 files changed

+42
-3
lines changed

openwisp_controller/config/admin.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -352,10 +352,13 @@ def get_temp_model_instance(self, **options):
352352
config_model = self.Meta.model
353353
instance = config_model(**options)
354354
device_model = config_model.device.field.related_model
355-
org = Organization.objects.get(pk=self.data["organization"])
355+
if not (org_id := self.data.get("organization")):
356+
# We cannot validate the templates without an organization.
357+
return
358+
org = Organization.objects.get(pk=org_id)
356359
instance.device = device_model(
357-
name=self.data["name"],
358-
mac_address=self.data["mac_address"],
360+
name=self.data.get("name", ""),
361+
mac_address=self.data.get("mac_address", ""),
359362
organization=org,
360363
)
361364
return instance
@@ -369,6 +372,12 @@ def clean_templates(self):
369372
# when adding self.instance is empty, we need to create a
370373
# temporary instance that we'll use just for validation
371374
config = self.get_temp_model_instance(**data)
375+
if not config:
376+
# The request does not contain vaild data to create a temporary
377+
# Device instance. Thus, we cannot validate the templates.
378+
# The Device validation will be handled by DeviceAdmin.
379+
# Therefore, we don't need to raise any error here.
380+
return
372381
else:
373382
config = self.instance
374383
if config.backend and templates:

openwisp_controller/config/tests/test_admin.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2279,6 +2279,36 @@ def test_templates_fetch_queries_10(self):
22792279
config = self._create_config(organization=self._get_org())
22802280
self._verify_template_queries(config, 10)
22812281

2282+
def test_empty_device_form_with_config_inline(self):
2283+
org = self._get_org()
2284+
template = self._create_template(organization=org)
2285+
path = reverse(f"admin:{self.app_label}_device_add")
2286+
# Submit form without required device fields but with config inline
2287+
# This reproduces the scenario where user clicks "Add another Configuration"
2288+
# and submits without filling device details
2289+
params = {
2290+
"config-0-backend": "netjsonconfig.OpenWrt",
2291+
"config-0-templates": str(template.pk),
2292+
"config-0-config": json.dumps({}),
2293+
"config-0-context": "",
2294+
"config-TOTAL_FORMS": 1,
2295+
"config-INITIAL_FORMS": 0,
2296+
"config-MIN_NUM_FORMS": 0,
2297+
"config-MAX_NUM_FORMS": 1,
2298+
"deviceconnection_set-TOTAL_FORMS": 0,
2299+
"deviceconnection_set-INITIAL_FORMS": 0,
2300+
"deviceconnection_set-MIN_NUM_FORMS": 0,
2301+
"deviceconnection_set-MAX_NUM_FORMS": 1000,
2302+
"command_set-TOTAL_FORMS": 0,
2303+
"command_set-INITIAL_FORMS": 0,
2304+
"command_set-MIN_NUM_FORMS": 0,
2305+
"command_set-MAX_NUM_FORMS": 1000,
2306+
}
2307+
response = self.client.post(path, params)
2308+
self.assertEqual(response.status_code, 200)
2309+
self.assertContains(response, "errorlist")
2310+
self.assertEqual(Device.objects.count(), 0)
2311+
22822312

22832313
class TestTransactionAdmin(
22842314
CreateConfigTemplateMixin,

0 commit comments

Comments
 (0)