Browse Source

Updated CSVForm validation

Jeremy Stretch 8 years ago
parent
commit
0a6e4f31d5
4 changed files with 68 additions and 85 deletions
  1. 31 37
      netbox/dcim/forms.py
  2. 36 44
      netbox/ipam/forms.py
  3. 1 3
      netbox/ipam/models.py
  4. 0 1
      netbox/templates/utilities/obj_import.html

+ 31 - 37
netbox/dcim/forms.py

@@ -5,7 +5,6 @@ import re
 
 from django import forms
 from django.contrib.postgres.forms.array import SimpleArrayField
-from django.core.exceptions import ValidationError
 from django.db.models import Count, Q
 
 from extras.forms import CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
@@ -228,14 +227,9 @@ class RackCSVForm(forms.ModelForm):
             'invalid_choice': 'Site not found.',
         }
     )
-    group = forms.ModelChoiceField(
-        queryset=RackGroup.objects.all(),
-        to_field_name='name',
-        required=False,
-        help_text='Name of parent rack group',
-        error_messages={
-            'invalid_choice': 'Rack group not found.',
-        }
+    group_name = forms.CharField(
+        help_text='Name of rack group',
+        required=False
     )
     tenant = forms.ModelChoiceField(
         queryset=Tenant.objects.all(),
@@ -274,13 +268,19 @@ class RackCSVForm(forms.ModelForm):
             'site', 'group', 'name', 'facility_id', 'tenant', 'role', 'type', 'width', 'u_height', 'desc_units',
         ]
 
-    def clean_group(self):
+    def clean(self):
+
+        super(RackCSVForm, self).clean()
 
         site = self.cleaned_data.get('site')
-        group = self.cleaned_data.get('group')
+        group_name = self.cleaned_data.get('group_name')
 
-        if group and group.site != site:
-            raise ValidationError("Invalid group for site {}: {}".format(site, group))
+        # Validate rack group
+        if group_name:
+            try:
+                self.instance.group = RackGroup.objects.get(site=site, name=group_name)
+            except RackGroup.DoesNotExist:
+                raise forms.ValidationError("Rack group {} not found for site {}".format(group_name, site))
 
 
 class RackBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
@@ -733,6 +733,8 @@ class BaseDeviceCSVForm(forms.ModelForm):
 
     def clean(self):
 
+        super(BaseDeviceCSVForm, self).clean()
+
         manufacturer = self.cleaned_data.get('manufacturer')
         model_name = self.cleaned_data.get('model_name')
 
@@ -741,7 +743,7 @@ class BaseDeviceCSVForm(forms.ModelForm):
             try:
                 self.instance.device_type = DeviceType.objects.get(manufacturer=manufacturer, model=model_name)
             except DeviceType.DoesNotExist:
-                self.add_error('model_name', "Invalid device type ({} {})".format(manufacturer, model_name))
+                raise forms.ValidationError("Device type {} {} not found".format(manufacturer, model_name))
 
 
 class DeviceCSVForm(BaseDeviceCSVForm):
@@ -753,6 +755,10 @@ class DeviceCSVForm(BaseDeviceCSVForm):
             'invalid_choice': 'Invalid site name.',
         }
     )
+    rack_group = forms.CharField(
+        required=False,
+        help_text='Name of parent rack\'s group'
+    )
     rack_name = forms.CharField(
         required=False,
         help_text='Name of parent rack'
@@ -766,7 +772,7 @@ class DeviceCSVForm(BaseDeviceCSVForm):
     class Meta(BaseDeviceCSVForm.Meta):
         fields = [
             'name', 'device_role', 'tenant', 'manufacturer', 'model_name', 'platform', 'serial', 'asset_tag', 'status',
-            'site', 'rack_name', 'position', 'face',
+            'site', 'rack_group', 'rack_name', 'position', 'face',
         ]
 
     def clean(self):
@@ -774,26 +780,20 @@ class DeviceCSVForm(BaseDeviceCSVForm):
         super(DeviceCSVForm, self).clean()
 
         site = self.cleaned_data.get('site')
+        rack_group = self.cleaned_data.get('rack_group')
         rack_name = self.cleaned_data.get('rack_name')
 
         # Validate rack
-        if site and rack_name:
+        if site and rack_group and rack_name:
             try:
-                self.instance.rack = Rack.objects.get(site=site, name=rack_name)
+                self.instance.rack = Rack.objects.get(site=site, group__name=rack_group, name=rack_name)
             except Rack.DoesNotExist:
-                self.add_error('rack_name', "Invalid rack ({})".format(rack_name))
-
-    def clean_face(self):
-        face = self.cleaned_data['face']
-        if not face:
-            return None
-        try:
-            return {
-                'front': 0,
-                'rear': 1,
-            }[face.lower()]
-        except KeyError:
-            raise forms.ValidationError('Invalid rack face ({}); must be "front" or "rear".'.format(face))
+                raise forms.ValidationError("Rack {} not found in site {} group {}".format(rack_name, site, rack_group))
+        elif site and rack_name:
+            try:
+                self.instance.rack = Rack.objects.get(site=site, group__isnull=True, name=rack_name)
+            except Rack.DoesNotExist:
+                raise forms.ValidationError("Rack {} not found in site {} (no group)".format(rack_name, site))
 
 
 class ChildDeviceCSVForm(BaseDeviceCSVForm):
@@ -825,13 +825,7 @@ class ChildDeviceCSVForm(BaseDeviceCSVForm):
         # Validate device bay
         if parent and device_bay_name:
             try:
-                device_bay = DeviceBay.objects.get(device=parent, name=device_bay_name)
-                if device_bay.installed_device:
-                    self.add_error(
-                        'device_bay_name', "Device bay ({} {}) is already occupied".format(parent, device_bay_name)
-                    )
-                else:
-                    self.instance.parent_bay = device_bay
+                self.instance.parent_bay = DeviceBay.objects.get(device=parent, name=device_bay_name)
             except DeviceBay.DoesNotExist:
                 self.add_error(
                     'device_bay_name', "Parent device/bay ({} {}) not found".format(parent, device_bay_name)

+ 36 - 44
netbox/ipam/forms.py

@@ -1,7 +1,6 @@
 from __future__ import unicode_literals
 
 from django import forms
-from django.core.exceptions import ValidationError
 from django.db.models import Count
 
 from dcim.models import Site, Rack, Device, Interface
@@ -230,7 +229,7 @@ class PrefixCSVForm(forms.ModelForm):
             'invalid_choice': 'Site not found.',
         }
     )
-    vlan_group_name = forms.CharField(
+    vlan_group = forms.CharField(
         help_text='Group name of assigned VLAN',
         required=False
     )
@@ -255,40 +254,36 @@ class PrefixCSVForm(forms.ModelForm):
     class Meta:
         model = Prefix
         fields = [
-            'prefix', 'vrf', 'tenant', 'site', 'vlan_group_name', 'vlan_vid', 'status', 'role', 'is_pool',
-            'description',
+            'prefix', 'vrf', 'tenant', 'site', 'vlan_group', 'vlan_vid', 'status', 'role', 'is_pool', 'description',
         ]
 
     def clean(self):
 
+        super(PrefixCSVForm, self).clean()
+
         site = self.cleaned_data.get('site')
-        vlan_group_name = self.cleaned_data.get('vlan_group_name')
+        vlan_group = self.cleaned_data.get('vlan_group')
         vlan_vid = self.cleaned_data.get('vlan_vid')
-        vlan_group = None
 
-        # Validate VLAN group
-        if vlan_group_name:
+        # Validate VLAN
+        if vlan_group and vlan_vid:
             try:
-                vlan_group = VLANGroup.objects.get(site=site, name=vlan_group_name)
-            except VLANGroup.DoesNotExist:
+                self.instance.vlan = VLAN.objects.get(site=site, group__name=vlan_group, vid=vlan_vid)
+            except VLAN.DoesNotExist:
                 if site:
-                    self.add_error('vlan_group_name', "Invalid VLAN group ({} - {}).".format(site, vlan_group_name))
+                    raise forms.ValidationError("VLAN {} not found in site {} group {}".format(
+                        vlan_vid, site, vlan_group
+                    ))
                 else:
-                    self.add_error('vlan_group_name', "Invalid global VLAN group ({}).".format(vlan_group_name))
-
-        # Validate VLAN
-        if vlan_vid:
+                    raise forms.ValidationError("Global VLAN {} not found in group {}".format(vlan_vid, vlan_group))
+        elif vlan_vid:
             try:
-                self.instance.vlan = VLAN.objects.get(site=site, group=vlan_group, vid=vlan_vid)
+                self.instance.vlan = VLAN.objects.get(site=site, group__isnull=True, vid=vlan_vid)
             except VLAN.DoesNotExist:
                 if site:
-                    self.add_error('vlan_vid', "Invalid VLAN ID ({}) for site {}.".format(vlan_vid, site))
-                elif vlan_group:
-                    self.add_error('vlan_vid', "Invalid VLAN ID ({}) for group {}.".format(vlan_vid, vlan_group_name))
-                elif not vlan_group_name:
-                    self.add_error('vlan_vid', "Invalid global VLAN ID ({}).".format(vlan_vid))
-            except VLAN.MultipleObjectsReturned:
-                self.add_error('vlan_vid', "Multiple VLANs found ({} - VID {})".format(site, vlan_vid))
+                    raise forms.ValidationError("VLAN {} not found in site {}".format(vlan_vid, site))
+                else:
+                    raise forms.ValidationError("Global VLAN {} not found".format(vlan_vid))
 
 
 class PrefixBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
@@ -589,6 +584,8 @@ class IPAddressCSVForm(forms.ModelForm):
 
     def clean(self):
 
+        super(IPAddressCSVForm, self).clean()
+
         device = self.cleaned_data.get('device')
         interface_name = self.cleaned_data.get('interface_name')
         is_primary = self.cleaned_data.get('is_primary')
@@ -596,17 +593,17 @@ class IPAddressCSVForm(forms.ModelForm):
         # Validate interface
         if device and interface_name:
             try:
-                Interface.objects.get(device=device, name=interface_name)
+                self.instance.interface = Interface.objects.get(device=device, name=interface_name)
             except Interface.DoesNotExist:
-                self.add_error('interface_name', "Invalid interface ({}) for {}".format(interface_name, device))
+                raise forms.ValidationError("Invalid interface {} for device {}".format(interface_name, device))
         elif device and not interface_name:
-            self.add_error('interface_name', "Device set ({}) but interface missing".format(device))
+            raise forms.ValidationError("Device set ({}) but interface missing".format(device))
         elif interface_name and not device:
-            self.add_error('device', "Interface set ({}) but device missing or invalid".format(interface_name))
+            raise forms.ValidationError("Interface set ({}) but device missing or invalid".format(interface_name))
 
         # Validate is_primary
         if is_primary and not device:
-            self.add_error('is_primary', "No device specified; cannot set as primary IP")
+            raise forms.ValidationError("No device specified; cannot set as primary IP")
 
     def save(self, *args, **kwargs):
 
@@ -732,7 +729,7 @@ class VLANCSVForm(forms.ModelForm):
         }
     )
     group_name = forms.CharField(
-        help_text='Name of parent VLAN group',
+        help_text='Name of VLAN group',
         required=False
     )
     tenant = forms.ModelChoiceField(
@@ -764,25 +761,20 @@ class VLANCSVForm(forms.ModelForm):
 
     def clean(self):
 
-        # Validate VLANGroup
+        super(VLANCSVForm, self).clean()
+
+        site = self.cleaned_data.get('site')
         group_name = self.cleaned_data.get('group_name')
+
+        # Validate VLAN group
         if group_name:
             try:
-                VLANGroup.objects.get(site=self.cleaned_data.get('site'), name=group_name)
+                self.instance.group = VLANGroup.objects.get(site=site, name=group_name)
             except VLANGroup.DoesNotExist:
-                self.add_error('group_name', "Invalid VLAN group {}.".format(group_name))
-
-    def save(self, *args, **kwargs):
-
-        vlan = super(VLANCSVForm, self).save(commit=False)
-
-        # Assign VLANGroup by site and name
-        if self.cleaned_data['group_name']:
-            vlan.group = VLANGroup.objects.get(site=self.cleaned_data['site'], name=self.cleaned_data['group_name'])
-
-        if kwargs.get('commit'):
-            vlan.save()
-        return vlan
+                if site:
+                    raise forms.ValidationError("VLAN group {} not found for site {}".format(group_name, site))
+                else:
+                    raise forms.ValidationError("Global VLAN group {} not found".format(group_name))
 
 
 class VLANBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):

+ 1 - 3
netbox/ipam/models.py

@@ -498,9 +498,7 @@ class VLANGroup(models.Model):
         verbose_name_plural = 'VLAN groups'
 
     def __str__(self):
-        if self.site is None:
-            return self.name
-        return '{} - {}'.format(self.site.name, self.name)
+        return self.name
 
     def get_absolute_url(self):
         return "{}?group_id={}".format(reverse('ipam:vlan_list'), self.pk)

+ 0 - 1
netbox/templates/utilities/obj_import.html

@@ -29,7 +29,6 @@
 		</form>
 	</div>
 	<div class="col-md-6">
-        {% block instructions %}{% endblock %}
         {% if fields %}
             <h4>CSV Format</h4>
             <table class="table">