Updated CSVForm validation

This commit is contained in:
Jeremy Stretch 2017-06-07 14:19:08 -04:00
parent e6c4ce51f7
commit 0a6e4f31d5
4 changed files with 71 additions and 88 deletions

View File

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

View File

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

View File

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

View File

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