Browse Source

Force validation of individual objects within a MultiObjectField

Jeremy Stretch 6 years ago
parent
commit
0615d368f2
3 changed files with 25 additions and 13 deletions
  1. 10 11
      netbox/dcim/forms.py
  2. 8 0
      netbox/utilities/forms.py
  3. 7 2
      netbox/utilities/views.py

+ 10 - 11
netbox/dcim/forms.py

@@ -848,7 +848,7 @@ class ConsolePortTemplateImportForm(ComponentTemplateImportForm):
     class Meta:
         model = ConsolePortTemplate
         fields = [
-            'device_type', 'name',
+            'name',
         ]
 
 
@@ -857,7 +857,7 @@ class ConsoleServerPortTemplateImportForm(ComponentTemplateImportForm):
     class Meta:
         model = ConsoleServerPortTemplate
         fields = [
-            'device_type', 'name',
+            'name',
         ]
 
 
@@ -866,7 +866,7 @@ class PowerPortTemplateImportForm(ComponentTemplateImportForm):
     class Meta:
         model = PowerPortTemplate
         fields = [
-            'device_type', 'name', 'maximum_draw', 'allocated_draw',
+            'name', 'maximum_draw', 'allocated_draw',
         ]
 
 
@@ -880,7 +880,7 @@ class PowerOutletTemplateImportForm(ComponentTemplateImportForm):
     class Meta:
         model = PowerOutletTemplate
         fields = [
-            'device_type', 'name', 'power_port', 'feed_leg',
+            'name', 'power_port', 'feed_leg',
         ]
 
 
@@ -889,7 +889,7 @@ class InterfaceTemplateImportForm(ComponentTemplateImportForm):
     class Meta:
         model = InterfaceTemplate
         fields = [
-            'device_type', 'name', 'type', 'mgmt_only',
+            'name', 'type', 'mgmt_only',
         ]
 
 
@@ -903,7 +903,7 @@ class FrontPortTemplateImportForm(ComponentTemplateImportForm):
     class Meta:
         model = FrontPortTemplate
         fields = [
-            'device_type', 'name', 'type', 'rear_port', 'rear_port_position',
+            'name', 'type', 'rear_port', 'rear_port_position',
         ]
 
 
@@ -912,7 +912,7 @@ class RearPortTemplateImportForm(ComponentTemplateImportForm):
     class Meta:
         model = RearPortTemplate
         fields = [
-            'device_type', 'name', 'type', 'positions',
+            'name', 'type', 'positions',
         ]
 
 
@@ -966,12 +966,11 @@ class DeviceTypeImportForm(BootstrapMixin, forms.ModelForm):
             for field_name, field in self.fields.items():
                 if isinstance(field, MultiObjectField):
                     for data in self.cleaned_data[field_name]:
-                        data.update({
-                            'device_type': instance.pk
-                        })
                         form = field.form(data)
                         if form.is_valid():
-                            form.save()
+                            component = form.save(commit=False)
+                            component.device_type = instance
+                            component.save()
 
         return instance
 

+ 8 - 0
netbox/utilities/forms.py

@@ -570,6 +570,14 @@ class MultiObjectField(forms.Field):
         if value is None:
             return list()
 
+        for i, obj_data in enumerate(value, start=1):
+            form = self.form(obj_data)
+            if not form.is_valid():
+                errors = [
+                   "Object {} {}: {}".format(i, field, errors) for field, errors in form.errors.items()
+                ]
+                raise forms.ValidationError(errors)
+
         return value
 
 

+ 7 - 2
netbox/utilities/views.py

@@ -443,9 +443,14 @@ class ObjectImportView(GetReturnURLMixin, View):
                     return redirect(self.get_return_url(request, obj))
 
             else:
+
                 # Replicate model form errors for display
-                for field, err in model_form.errors.items():
-                    form.add_error(None, "{}: {}".format(field, err))
+                for field, errors in model_form.errors.items():
+                    for err in errors:
+                        if field == '__all__':
+                            form.add_error(None, err)
+                        else:
+                            form.add_error(None, "{}: {}".format(field, err))
 
         return render(request, self.template_name, {
             'form': form,