Przeglądaj źródła

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

Jeremy Stretch 5 lat temu
rodzic
commit
b2e05aafc1

+ 5 - 0
netbox/dcim/forms.py

@@ -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')

+ 2 - 0
netbox/dcim/models/device_component_templates.py

@@ -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:

+ 6 - 0
netbox/dcim/models/device_components.py

@@ -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:

+ 1 - 0
netbox/dcim/models/racks.py

@@ -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:

+ 4 - 0
netbox/extras/models/customfields.py

@@ -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:

+ 5 - 1
netbox/extras/models/models.py

@@ -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

+ 2 - 0
netbox/users/admin.py

@@ -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')
 
 

+ 2 - 0
netbox/utilities/forms/forms.py

@@ -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']

+ 1 - 0
netbox/virtualization/models.py

@@ -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]: