1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Closes #5531: Ensure consistent calls to parent clean() methods for models, forms

This commit is contained in:
Jeremy Stretch
2020-12-28 12:54:42 -05:00
parent cc1a43e5d9
commit b2e05aafc1
9 changed files with 28 additions and 1 deletions

View File

@ -134,6 +134,7 @@ class ComponentForm(BootstrapMixin, forms.Form):
) )
def clean(self): def clean(self):
super().clean()
# Validate that the number of components being created from both the name_pattern and label_pattern are equal # Validate that the number of components being created from both the name_pattern and label_pattern are equal
if self.cleaned_data['label_pattern']: if self.cleaned_data['label_pattern']:
@ -1438,6 +1439,7 @@ class FrontPortTemplateCreateForm(ComponentTemplateCreateForm):
self.fields['rear_port_set'].choices = choices self.fields['rear_port_set'].choices = choices
def clean(self): def clean(self):
super().clean()
# Validate that the number of ports being created equals the number of selected (rear port, position) tuples # Validate that the number of ports being created equals the number of selected (rear port, position) tuples
front_port_count = len(self.cleaned_data['name_pattern']) front_port_count = len(self.cleaned_data['name_pattern'])
@ -2929,6 +2931,7 @@ class InterfaceBulkEditForm(
self.fields['lag'].widget.attrs['disabled'] = True self.fields['lag'].widget.attrs['disabled'] = True
def clean(self): def clean(self):
super().clean()
# Untagged interfaces cannot be assigned tagged VLANs # Untagged interfaces cannot be assigned tagged VLANs
if self.cleaned_data['mode'] == InterfaceModeChoices.MODE_ACCESS and self.cleaned_data['tagged_vlans']: if self.cleaned_data['mode'] == InterfaceModeChoices.MODE_ACCESS and self.cleaned_data['tagged_vlans']:
@ -3077,6 +3080,7 @@ class FrontPortCreateForm(ComponentCreateForm):
self.fields['rear_port_set'].choices = choices self.fields['rear_port_set'].choices = choices
def clean(self): def clean(self):
super().clean()
# Validate that the number of ports being created equals the number of selected (rear port, position) tuples # Validate that the number of ports being created equals the number of selected (rear port, position) tuples
front_port_count = len(self.cleaned_data['name_pattern']) front_port_count = len(self.cleaned_data['name_pattern'])
@ -3909,6 +3913,7 @@ class CableBulkEditForm(BootstrapMixin, AddRemoveTagsForm, BulkEditForm):
] ]
def clean(self): def clean(self):
super().clean()
# Validate length/unit # Validate length/unit
length = self.cleaned_data.get('length') length = self.cleaned_data.get('length')

View File

@ -193,6 +193,7 @@ class PowerOutletTemplate(ComponentTemplateModel):
unique_together = ('device_type', 'name') unique_together = ('device_type', 'name')
def clean(self): def clean(self):
super().clean()
# Validate power port assignment # Validate power port assignment
if self.power_port and self.power_port.device_type != self.device_type: if self.power_port and self.power_port.device_type != self.device_type:
@ -278,6 +279,7 @@ class FrontPortTemplate(ComponentTemplateModel):
) )
def clean(self): def clean(self):
super().clean()
# Validate rear port assignment # Validate rear port assignment
if self.rear_port.device_type != self.device_type: if self.rear_port.device_type != self.device_type:

View File

@ -316,6 +316,7 @@ class PowerPort(CableTermination, PathEndpoint, ComponentModel):
) )
def clean(self): def clean(self):
super().clean()
if self.maximum_draw is not None and self.allocated_draw is not None: if self.maximum_draw is not None and self.allocated_draw is not None:
if self.allocated_draw > self.maximum_draw: if self.allocated_draw > self.maximum_draw:
@ -425,6 +426,7 @@ class PowerOutlet(CableTermination, PathEndpoint, ComponentModel):
) )
def clean(self): def clean(self):
super().clean()
# Validate power port assignment # Validate power port assignment
if self.power_port and self.power_port.device != self.device: if self.power_port and self.power_port.device != self.device:
@ -555,6 +557,7 @@ class Interface(CableTermination, PathEndpoint, ComponentModel, BaseInterface):
) )
def clean(self): def clean(self):
super().clean()
# Virtual interfaces cannot be connected # Virtual interfaces cannot be connected
if self.type in NONCONNECTABLE_IFACE_TYPES and ( if self.type in NONCONNECTABLE_IFACE_TYPES and (
@ -668,6 +671,7 @@ class FrontPort(CableTermination, ComponentModel):
) )
def clean(self): def clean(self):
super().clean()
# Validate rear port assignment # Validate rear port assignment
if self.rear_port.device != self.device: if self.rear_port.device != self.device:
@ -711,6 +715,7 @@ class RearPort(CableTermination, ComponentModel):
return reverse('dcim:rearport', kwargs={'pk': self.pk}) return reverse('dcim:rearport', kwargs={'pk': self.pk})
def clean(self): def clean(self):
super().clean()
# Check that positions count is greater than or equal to the number of associated FrontPorts # Check that positions count is greater than or equal to the number of associated FrontPorts
frontport_count = self.frontports.count() frontport_count = self.frontports.count()
@ -768,6 +773,7 @@ class DeviceBay(ComponentModel):
) )
def clean(self): def clean(self):
super().clean()
# Validate that the parent Device can have DeviceBays # Validate that the parent Device can have DeviceBays
if not self.device.device_type.is_parent_device: if not self.device.device_type.is_parent_device:

View File

@ -109,6 +109,7 @@ class RackGroup(MPTTModel, ChangeLoggedModel):
) )
def clean(self): def clean(self):
super().clean()
# Parent RackGroup (if any) must belong to the same Site # Parent RackGroup (if any) must belong to the same Site
if self.parent and self.parent.site != self.site: if self.parent and self.parent.site != self.site:

View File

@ -47,6 +47,8 @@ class CustomFieldModel(models.Model):
]) ])
def clean(self): def clean(self):
super().clean()
custom_fields = {cf.name: cf for cf in CustomField.objects.get_for_model(self)} custom_fields = {cf.name: cf for cf in CustomField.objects.get_for_model(self)}
# Validate all field values # Validate all field values
@ -172,6 +174,8 @@ class CustomField(models.Model):
obj.save() obj.save()
def clean(self): def clean(self):
super().clean()
# Validate the field's default value (if any) # Validate the field's default value (if any)
if self.default is not None: if self.default is not None:
try: try:

View File

@ -117,11 +117,15 @@ class Webhook(models.Model):
return self.name return self.name
def clean(self): def clean(self):
super().clean()
# At least one action type must be selected
if not self.type_create and not self.type_delete and not self.type_update: if not self.type_create and not self.type_delete and not self.type_update:
raise ValidationError( raise ValidationError(
"You must select at least one type: create, update, and/or delete." "You must select at least one type: create, update, and/or delete."
) )
# CA file path requires SSL verification enabled
if not self.ssl_verification and self.ca_file_path: if not self.ssl_verification and self.ca_file_path:
raise ValidationError({ raise ValidationError({
'ca_file_path': 'Do not specify a CA certificate file if SSL verification is disabled.' 'ca_file_path': 'Do not specify a CA certificate file if SSL verification is disabled.'
@ -436,6 +440,7 @@ class ConfigContext(ChangeLoggedModel):
return reverse('extras:configcontext', kwargs={'pk': self.pk}) return reverse('extras:configcontext', kwargs={'pk': self.pk})
def clean(self): def clean(self):
super().clean()
# Verify that JSON data is provided as an object # Verify that JSON data is provided as an object
if type(self.data) is not dict: if type(self.data) is not dict:
@ -482,7 +487,6 @@ class ConfigContextModel(models.Model):
return data return data
def clean(self): def clean(self):
super().clean() super().clean()
# Verify that JSON data is provided as an object # Verify that JSON data is provided as an object

View File

@ -169,6 +169,8 @@ class ObjectPermissionForm(forms.ModelForm):
self.instance.actions.remove(action) self.instance.actions.remove(action)
def clean(self): def clean(self):
super().clean()
object_types = self.cleaned_data.get('object_types') object_types = self.cleaned_data.get('object_types')
constraints = self.cleaned_data.get('constraints') constraints = self.cleaned_data.get('constraints')

View File

@ -82,6 +82,7 @@ class BulkRenameForm(forms.Form):
) )
def clean(self): def clean(self):
super().clean()
# Validate regular expression in "find" field # Validate regular expression in "find" field
if self.cleaned_data['use_regex']: if self.cleaned_data['use_regex']:
@ -124,6 +125,7 @@ class ImportForm(BootstrapMixin, forms.Form):
) )
def clean(self): def clean(self):
super().clean()
data = self.cleaned_data['data'] data = self.cleaned_data['data']
format = self.cleaned_data['format'] format = self.cleaned_data['format']

View File

@ -444,6 +444,7 @@ class VMInterface(BaseInterface):
) )
def clean(self): def clean(self):
super().clean()
# Validate untagged VLAN # Validate untagged VLAN
if self.untagged_vlan and self.untagged_vlan.site not in [self.virtual_machine.site, None]: if self.untagged_vlan and self.untagged_vlan.site not in [self.virtual_machine.site, None]: