mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-24 17:38:37 -06:00
Updated CSVForm validation
This commit is contained in:
parent
e6c4ce51f7
commit
0a6e4f31d5
@ -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)
|
||||||
|
@ -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):
|
||||||
|
@ -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)
|
||||||
|
@ -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">
|
||||||
|
Loading…
Reference in New Issue
Block a user