mirror of
https://github.com/netbox-community/netbox.git
synced 2025-12-23 13:52:17 -06:00
* Allow re-assigning InventoryItem components * Refactor logic for finding initial component assignment on InventoryItems * PEP8 fix * Fix wrong HTML causing tab list to extend past the end of the parent row * Tweak form field labels Co-authored-by: jeremystretch <jstretch@ns1.com>
This commit is contained in:
@@ -1549,15 +1549,63 @@ class InventoryItemForm(DeviceComponentForm):
|
||||
queryset=Manufacturer.objects.all(),
|
||||
required=False
|
||||
)
|
||||
component_type = ContentTypeChoiceField(
|
||||
queryset=ContentType.objects.all(),
|
||||
limit_choices_to=MODULAR_COMPONENT_MODELS,
|
||||
|
||||
# Assigned component selectors
|
||||
consoleport = DynamicModelChoiceField(
|
||||
queryset=ConsolePort.objects.all(),
|
||||
required=False,
|
||||
widget=forms.HiddenInput
|
||||
query_params={
|
||||
'device_id': '$device'
|
||||
},
|
||||
label=_('Console port')
|
||||
)
|
||||
component_id = forms.IntegerField(
|
||||
consoleserverport = DynamicModelChoiceField(
|
||||
queryset=ConsoleServerPort.objects.all(),
|
||||
required=False,
|
||||
widget=forms.HiddenInput
|
||||
query_params={
|
||||
'device_id': '$device'
|
||||
},
|
||||
label=_('Console server port')
|
||||
)
|
||||
frontport = DynamicModelChoiceField(
|
||||
queryset=FrontPort.objects.all(),
|
||||
required=False,
|
||||
query_params={
|
||||
'device_id': '$device'
|
||||
},
|
||||
label=_('Front port')
|
||||
)
|
||||
interface = DynamicModelChoiceField(
|
||||
queryset=Interface.objects.all(),
|
||||
required=False,
|
||||
query_params={
|
||||
'device_id': '$device'
|
||||
},
|
||||
label=_('Interface')
|
||||
)
|
||||
poweroutlet = DynamicModelChoiceField(
|
||||
queryset=PowerOutlet.objects.all(),
|
||||
required=False,
|
||||
query_params={
|
||||
'device_id': '$device'
|
||||
},
|
||||
label=_('Power outlet')
|
||||
)
|
||||
powerport = DynamicModelChoiceField(
|
||||
queryset=PowerPort.objects.all(),
|
||||
required=False,
|
||||
query_params={
|
||||
'device_id': '$device'
|
||||
},
|
||||
label=_('Power port')
|
||||
)
|
||||
rearport = DynamicModelChoiceField(
|
||||
queryset=RearPort.objects.all(),
|
||||
required=False,
|
||||
query_params={
|
||||
'device_id': '$device'
|
||||
},
|
||||
label=_('Rear port')
|
||||
)
|
||||
|
||||
fieldsets = (
|
||||
@@ -1565,22 +1613,61 @@ class InventoryItemForm(DeviceComponentForm):
|
||||
('Hardware', ('manufacturer', 'part_id', 'serial', 'asset_tag')),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = InventoryItem
|
||||
fields = [
|
||||
'device', 'parent', 'name', 'label', 'role', 'manufacturer', 'part_id', 'serial', 'asset_tag',
|
||||
'description', 'tags',
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
instance = kwargs.get('instance')
|
||||
initial = kwargs.get('initial', {}).copy()
|
||||
component_type = initial.get('component_type')
|
||||
component_id = initial.get('component_id')
|
||||
|
||||
# Used for picking the default active tab for component selection
|
||||
self.no_component = True
|
||||
|
||||
if instance:
|
||||
# When editing set the initial value for component selectin
|
||||
for component_model in ContentType.objects.filter(MODULAR_COMPONENT_MODELS):
|
||||
if type(instance.component) is component_model.model_class():
|
||||
initial[component_model.model] = instance.component
|
||||
self.no_component = False
|
||||
break
|
||||
elif component_type and component_id:
|
||||
# When adding the InventoryItem from a component page
|
||||
if content_type := ContentType.objects.filter(MODULAR_COMPONENT_MODELS).filter(pk=component_type).first():
|
||||
if component := content_type.model_class().objects.filter(pk=component_id).first():
|
||||
initial[content_type.model] = component
|
||||
self.no_component = False
|
||||
|
||||
kwargs['initial'] = initial
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
# Specifically allow editing the device of IntentoryItems
|
||||
if self.instance.pk:
|
||||
self.fields['device'].disabled = False
|
||||
|
||||
class Meta:
|
||||
model = InventoryItem
|
||||
fields = [
|
||||
'device', 'parent', 'name', 'label', 'role', 'manufacturer', 'part_id', 'serial', 'asset_tag',
|
||||
'description', 'component_type', 'component_id', 'tags',
|
||||
def clean(self):
|
||||
super().clean()
|
||||
|
||||
# Handle object assignment
|
||||
selected_objects = [
|
||||
field for field in (
|
||||
'consoleport', 'consoleserverport', 'frontport', 'interface', 'poweroutlet', 'powerport', 'rearport'
|
||||
) if self.cleaned_data[field]
|
||||
]
|
||||
if len(selected_objects) > 1:
|
||||
raise forms.ValidationError("An InventoryItem can only be assigned to a single component.")
|
||||
elif selected_objects:
|
||||
self.instance.component = self.cleaned_data[selected_objects[0]]
|
||||
else:
|
||||
self.instance.component = None
|
||||
|
||||
|
||||
#
|
||||
# Device component roles
|
||||
#
|
||||
|
||||
|
||||
@@ -1146,3 +1146,8 @@ class InventoryItem(MPTTModel, ComponentModel):
|
||||
# When moving an InventoryItem to another device, remove any associated component
|
||||
if self.component and self.component.device != self.device:
|
||||
self.component = None
|
||||
else:
|
||||
if self.component and self.component.device != self.device:
|
||||
raise ValidationError({
|
||||
"device": "Cannot assign inventory item to component on another device"
|
||||
})
|
||||
|
||||
@@ -2914,23 +2914,14 @@ class InventoryItemView(generic.ObjectView):
|
||||
class InventoryItemEditView(generic.ObjectEditView):
|
||||
queryset = InventoryItem.objects.all()
|
||||
form = forms.InventoryItemForm
|
||||
template_name = 'dcim/inventoryitem_edit.html'
|
||||
|
||||
|
||||
class InventoryItemCreateView(generic.ComponentCreateView):
|
||||
queryset = InventoryItem.objects.all()
|
||||
form = forms.InventoryItemCreateForm
|
||||
model_form = forms.InventoryItemForm
|
||||
|
||||
def alter_object(self, instance, request):
|
||||
# Set component (if any)
|
||||
component_type = request.GET.get('component_type')
|
||||
component_id = request.GET.get('component_id')
|
||||
|
||||
if component_type and component_id:
|
||||
content_type = get_object_or_404(ContentType, pk=component_type)
|
||||
instance.component = get_object_or_404(content_type.model_class(), pk=component_id)
|
||||
|
||||
return instance
|
||||
template_name = 'dcim/inventoryitem_edit.html'
|
||||
|
||||
|
||||
@register_model_view(InventoryItem, 'delete')
|
||||
|
||||
Reference in New Issue
Block a user