Przeglądaj źródła

Closes #12133: Move any instance mutations inside clean() to save()

jeremystretch 2 lat temu
rodzic
commit
b032742418

+ 4 - 2
netbox/dcim/models/cables.py

@@ -152,8 +152,6 @@ class Cable(PrimaryModel):
         # Validate length and length_unit
         if self.length is not None and not self.length_unit:
             raise ValidationError("Must specify a unit when setting a cable length")
-        elif self.length is None:
-            self.length_unit = ''
 
         if self.pk is None and (not self.a_terminations or not self.b_terminations):
             raise ValidationError("Must define A and B terminations when creating a new cable.")
@@ -187,6 +185,10 @@ class Cable(PrimaryModel):
         else:
             self._abs_length = None
 
+        # Clear length_unit if no length is defined
+        if self.length is None:
+            self.length_unit = ''
+
         super().save(*args, **kwargs)
 
         # Update the private pk used in __str__ in case this is a new object (i.e. just got its pk)

+ 10 - 4
netbox/dcim/models/device_components.py

@@ -794,8 +794,6 @@ class Interface(ModularComponentModel, BaseInterface, CabledObjectModel, PathEnd
                 raise ValidationError({
                     'rf_channel_frequency': "Cannot specify custom frequency with channel selected.",
                 })
-        elif self.rf_channel:
-            self.rf_channel_frequency = get_channel_attr(self.rf_channel, 'frequency')
 
         # Validate channel width against interface type and selected channel (if any)
         if self.rf_channel_width:
@@ -803,8 +801,6 @@ class Interface(ModularComponentModel, BaseInterface, CabledObjectModel, PathEnd
                 raise ValidationError({'rf_channel_width': "Channel width may be set only on wireless interfaces."})
             if self.rf_channel and self.rf_channel_width != get_channel_attr(self.rf_channel, 'width'):
                 raise ValidationError({'rf_channel_width': "Cannot specify custom width with channel selected."})
-        elif self.rf_channel:
-            self.rf_channel_width = get_channel_attr(self.rf_channel, 'width')
 
         # VLAN validation
 
@@ -815,6 +811,16 @@ class Interface(ModularComponentModel, BaseInterface, CabledObjectModel, PathEnd
                                  f"interface's parent device, or it must be global."
             })
 
+    def save(self, *args, **kwargs):
+
+        # Set absolute channel attributes from selected options
+        if self.rf_channel and not self.rf_channel_frequency:
+            self.rf_channel_frequency = get_channel_attr(self.rf_channel, 'frequency')
+        if self.rf_channel and not self.rf_channel_width:
+            self.rf_channel_width = get_channel_attr(self.rf_channel, 'width')
+
+        super().save(*args, **kwargs)
+
     @property
     def _occupied(self):
         return super()._occupied or bool(self.wireless_link_id)

+ 4 - 2
netbox/dcim/models/racks.py

@@ -222,8 +222,6 @@ class Rack(PrimaryModel, WeightMixin):
         # Validate outer dimensions and unit
         if (self.outer_width is not None or self.outer_depth is not None) and not self.outer_unit:
             raise ValidationError("Must specify a unit when setting an outer width/depth")
-        elif self.outer_width is None and self.outer_depth is None:
-            self.outer_unit = ''
 
         # Validate max_weight and weight_unit
         if self.max_weight and not self.weight_unit:
@@ -259,6 +257,10 @@ class Rack(PrimaryModel, WeightMixin):
         else:
             self._abs_max_weight = None
 
+        # Clear unit if outer width & depth are not set
+        if self.outer_width is None and self.outer_depth is None:
+            self.outer_unit = ''
+
         super().save(*args, **kwargs)
 
     @property

+ 0 - 3
netbox/ipam/models/ip.py

@@ -178,9 +178,6 @@ class Aggregate(GetAvailablePrefixesMixin, PrimaryModel):
 
         if self.prefix:
 
-            # Clear host bits from prefix
-            self.prefix = self.prefix.cidr
-
             # /0 masks are not acceptable
             if self.prefix.prefixlen == 0:
                 raise ValidationError({

+ 8 - 2
netbox/virtualization/models/virtualmachines.py

@@ -169,8 +169,6 @@ class VirtualMachine(PrimaryModel, ConfigContextModel):
             raise ValidationError({
                 'cluster': f'The selected cluster ({self.cluster}) is not assigned to this site ({self.site}).'
             })
-        elif self.cluster:
-            self.site = self.cluster.site
 
         # Validate assigned cluster device
         if self.device and not self.cluster:
@@ -201,6 +199,14 @@ class VirtualMachine(PrimaryModel, ConfigContextModel):
                         field: f"The specified IP address ({ip}) is not assigned to this VM.",
                     })
 
+    def save(self, *args, **kwargs):
+
+        # Assign site from cluster if not set
+        if self.cluster and not self.site:
+            self.site = self.cluster.site
+
+        super().save(*args, **kwargs)
+
     def get_status_color(self):
         return VirtualMachineStatusChoices.colors.get(self.status)
 

+ 1 - 1
netbox/virtualization/tests/test_models.py

@@ -72,7 +72,7 @@ class VirtualMachineTestCase(TestCase):
 
         # VM with cluster site but no direct site should have its site set automatically
         vm = VirtualMachine(name='vm1', site=None, cluster=clusters[0])
-        vm.full_clean()
+        vm.save()
         self.assertEqual(vm.site, sites[0])
 
     def test_vm_name_case_sensitivity(self):