diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index 930ac166b..ec293b7e1 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -27,6 +27,7 @@ from utilities.forms import ( NumericArrayField, SelectWithPK, SmallTextarea, SlugField, StaticSelect2, StaticSelect2Multiple, TagFilterField, BOOLEAN_WITH_BLANK_CHOICES, ) +from utilities.utils import union_list from virtualization.models import Cluster, ClusterGroup from .choices import * from .constants import * @@ -1910,6 +1911,18 @@ class DeviceForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): elif self.initial.get('rack') and str(self.initial.get('face')): position_choices = Rack.objects.get(pk=self.initial['rack']) \ .get_rack_units(face=self.initial.get('face'), exclude=pk) + elif self.is_bound and self.data.get('rack'): + front = Rack.objects.get(pk=self.data['rack']) \ + .get_rack_units(face=DeviceFaceChoices.FACE_FRONT, exclude=pk) + rear = Rack.objects.get(pk=self.data['rack']) \ + .get_rack_units(face=DeviceFaceChoices.FACE_REAR, exclude=pk) + position_choices = union_list(front, rear, 'name') + elif self.initial.get('rack'): + front = Rack.objects.get(pk=self.initial['rack']) \ + .get_rack_units(face=DeviceFaceChoices.FACE_FRONT, exclude=pk) + rear = Rack.objects.get(pk=self.initial['rack']) \ + .get_rack_units(face=DeviceFaceChoices.FACE_REAR, exclude=pk) + position_choices = union_list(front, rear, 'name') else: position_choices = [] except Rack.DoesNotExist: diff --git a/netbox/utilities/utils.py b/netbox/utilities/utils.py index d76b469b2..512fe4e78 100644 --- a/netbox/utilities/utils.py +++ b/netbox/utilities/utils.py @@ -83,6 +83,30 @@ def count_related(model, field): return Coalesce(subquery, 0) +def intersect_list(llist, rlist, key): + result = [] + for left in llist: + for right in rlist: + if isinstance(left, dict) and isinstance(right, dict) and key in left.keys() and key in right.keys() and \ + left[key] == right[key]: + result.append(left) + break + return result + + +def union_list(llist, rlist, key): + result = llist + for right in rlist: + found = False + for left in llist: + if isinstance(left, dict) and isinstance(right, dict) and key in left.keys() and key in right.keys() and \ + left[key] == right[key]: + found = True + if found is False: + result.append(right) + return result + + def serialize_object(obj, extra=None, exclude=None): """ Return a generic JSON representation of an object using Django's built-in serializer. (This is used for things like