diff --git a/netbox/dcim/forms/bulk_edit.py b/netbox/dcim/forms/bulk_edit.py index 72407b6dd..c07db9557 100644 --- a/netbox/dcim/forms/bulk_edit.py +++ b/netbox/dcim/forms/bulk_edit.py @@ -304,20 +304,9 @@ class RackBulkEditForm(NetBoxModelBulkEditForm): ('Weight', ('weight', 'weight_unit')), ) nullable_fields = ( - 'location', 'tenant', 'role', 'serial', 'asset_tag', 'outer_width', 'outer_depth', 'outer_unit', 'comments', 'weight' + 'location', 'tenant', 'role', 'serial', 'asset_tag', 'outer_width', 'outer_depth', 'outer_unit', 'comments', 'weight', 'weight_unit' ) - def clean(self): - super().clean() - - # Validate weight/unit - weight = self.cleaned_data.get('weight') - weight_unit = self.cleaned_data.get('weight_unit') - if weight and not weight_unit: - raise forms.ValidationError({ - 'weight_unit': "Must specify a unit when setting weight" - }) - class RackReservationBulkEditForm(NetBoxModelBulkEditForm): user = forms.ModelChoiceField( @@ -393,18 +382,7 @@ class DeviceTypeBulkEditForm(NetBoxModelBulkEditForm): (None, ('manufacturer', 'part_number', 'u_height', 'is_full_depth', 'airflow')), ('Weight', ('weight', 'weight_unit')), ) - nullable_fields = ('part_number', 'airflow', 'weight') - - def clean(self): - super().clean() - - # Validate weight/unit - weight = self.cleaned_data.get('weight') - weight_unit = self.cleaned_data.get('weight_unit') - if weight and not weight_unit: - raise forms.ValidationError({ - 'weight_unit': "Must specify a unit when setting weight" - }) + nullable_fields = ('part_number', 'airflow', 'weight', 'weight_unit') class ModuleTypeBulkEditForm(NetBoxModelBulkEditForm): @@ -431,18 +409,7 @@ class ModuleTypeBulkEditForm(NetBoxModelBulkEditForm): (None, ('manufacturer', 'part_number')), ('Attributes', ('weight', 'weight_unit')), ) - nullable_fields = ('part_number', 'weight',) - - def clean(self): - super().clean() - - # Validate weight/unit - weight = self.cleaned_data.get('weight') - weight_unit = self.cleaned_data.get('weight_unit') - if weight and not weight_unit: - raise forms.ValidationError({ - 'weight_unit': "Must specify a unit when setting weight" - }) + nullable_fields = ('part_number', 'weight', 'weight_unit') class DeviceRoleBulkEditForm(NetBoxModelBulkEditForm): @@ -619,17 +586,6 @@ class CableBulkEditForm(NetBoxModelBulkEditForm): 'type', 'status', 'tenant', 'label', 'color', 'length', ) - def clean(self): - super().clean() - - # Validate length/unit - length = self.cleaned_data.get('length') - length_unit = self.cleaned_data.get('length_unit') - if length and not length_unit: - raise forms.ValidationError({ - 'length_unit': "Must specify a unit when setting length" - }) - class VirtualChassisBulkEditForm(NetBoxModelBulkEditForm): domain = forms.CharField( diff --git a/netbox/dcim/forms/filtersets.py b/netbox/dcim/forms/filtersets.py index 9647b9c26..818da83e1 100644 --- a/netbox/dcim/forms/filtersets.py +++ b/netbox/dcim/forms/filtersets.py @@ -228,7 +228,7 @@ class RackFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFilte ('Hardware', ('type', 'width', 'serial', 'asset_tag')), ('Tenant', ('tenant_group_id', 'tenant_id')), ('Contacts', ('contact', 'contact_role', 'contact_group')), - ('Attributes', ('weight', 'weight_unit')), + ('Weight', ('weight', 'weight_unit')), ) region_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), diff --git a/netbox/dcim/models/devices.py b/netbox/dcim/models/devices.py index b15202ac1..20c15f1ca 100644 --- a/netbox/dcim/models/devices.py +++ b/netbox/dcim/models/devices.py @@ -1,7 +1,8 @@ import decimal - import yaml +from functools import cached_property + from django.apps import apps from django.contrib.contenttypes.fields import GenericRelation from django.core.exceptions import ValidationError @@ -946,6 +947,13 @@ class Device(NetBoxModel, ConfigContextModel): def get_status_color(self): return DeviceStatusChoices.colors.get(self.status) + @cached_property + def get_total_weight(self): + total_weight = sum(module.module_type._abs_weight for module in Module.objects.filter(device=self).exclude(module_type___abs_weight__isnull=True).prefetch_related('module_type')) + if self.device_type._abs_weight: + total_weight += self.device_type._abs_weight + return round(total_weight / 1000, 2) + class Module(NetBoxModel, ConfigContextModel): """ diff --git a/netbox/dcim/models/racks.py b/netbox/dcim/models/racks.py index 45c138bf4..4744784bf 100644 --- a/netbox/dcim/models/racks.py +++ b/netbox/dcim/models/racks.py @@ -1,4 +1,5 @@ import decimal +from functools import cached_property from django.apps import apps from django.contrib.auth.models import User @@ -455,6 +456,7 @@ class Rack(NetBoxModel, WeightMixin): return int(allocated_draw / available_power_total * 100) + @cached_property def get_total_weight(self): total_weight = sum(device.device_type._abs_weight for device in self.devices.exclude(device_type___abs_weight__isnull=True).prefetch_related('device_type')) total_weight += sum(module.module_type._abs_weight for module in Module.objects.filter(device__rack=self).exclude(module_type___abs_weight__isnull=True).prefetch_related('module_type'))