فهرست منبع

Fixes #11528: Permit import of devices using uploaded file

jeremystretch 3 سال پیش
والد
کامیت
b8de9c0875

+ 32 - 45
netbox/dcim/forms/bulk_import.py

@@ -18,7 +18,6 @@ from .common import ModuleCommonForm
 
 __all__ = (
     'CableImportForm',
-    'ChildDeviceImportForm',
     'ConsolePortImportForm',
     'ConsoleServerPortImportForm',
     'DeviceBayImportForm',
@@ -413,6 +412,18 @@ class DeviceImportForm(BaseDeviceImportForm):
         required=False,
         help_text=_('Mounted rack face')
     )
+    parent = CSVModelChoiceField(
+        queryset=Device.objects.all(),
+        to_field_name='name',
+        required=False,
+        help_text=_('Parent device (for child devices)')
+    )
+    device_bay = CSVModelChoiceField(
+        queryset=DeviceBay.objects.all(),
+        to_field_name='name',
+        required=False,
+        help_text=_('Device bay in which this device is installed (for child devices)')
+    )
     airflow = CSVChoiceField(
         choices=DeviceAirflowChoices,
         required=False,
@@ -422,8 +433,8 @@ class DeviceImportForm(BaseDeviceImportForm):
     class Meta(BaseDeviceImportForm.Meta):
         fields = [
             'name', 'device_role', 'tenant', 'manufacturer', 'device_type', 'platform', 'serial', 'asset_tag', 'status',
-            'site', 'location', 'rack', 'position', 'face', 'airflow', 'virtual_chassis', 'vc_position', 'vc_priority',
-            'cluster', 'description', 'comments', 'tags',
+            'site', 'location', 'rack', 'position', 'face', 'parent', 'device_bay', 'airflow', 'virtual_chassis',
+            'vc_position', 'vc_priority', 'cluster', 'description', 'comments', 'tags',
         ]
 
     def __init__(self, data=None, *args, **kwargs):
@@ -434,6 +445,7 @@ class DeviceImportForm(BaseDeviceImportForm):
             # Limit location queryset by assigned site
             params = {f"site__{self.fields['site'].to_field_name}": data.get('site')}
             self.fields['location'].queryset = self.fields['location'].queryset.filter(**params)
+            self.fields['parent'].queryset = self.fields['parent'].queryset.filter(**params)
 
             # Limit rack queryset by assigned site and group
             params = {
@@ -442,6 +454,23 @@ class DeviceImportForm(BaseDeviceImportForm):
             }
             self.fields['rack'].queryset = self.fields['rack'].queryset.filter(**params)
 
+            # Limit device bay queryset by parent device
+            if parent := data.get('parent'):
+                params = {f"device__{self.fields['parent'].to_field_name}": parent}
+                self.fields['device_bay'].queryset = self.fields['device_bay'].queryset.filter(**params)
+
+    def clean(self):
+        super().clean()
+
+        # Inherit site and rack from parent device
+        if parent := self.cleaned_data.get('parent'):
+            self.instance.site = parent.site
+            self.instance.rack = parent.rack
+
+        # Set parent_bay reverse relationship
+        if device_bay := self.cleaned_data.get('device_bay'):
+            self.instance.parent_bay = device_bay
+
 
 class ModuleImportForm(ModuleCommonForm, NetBoxModelImportForm):
     device = CSVModelChoiceField(
@@ -495,48 +524,6 @@ class ModuleImportForm(ModuleCommonForm, NetBoxModelImportForm):
             return self.cleaned_data['replicate_components']
 
 
-class ChildDeviceImportForm(BaseDeviceImportForm):
-    parent = CSVModelChoiceField(
-        queryset=Device.objects.all(),
-        to_field_name='name',
-        help_text=_('Parent device')
-    )
-    device_bay = CSVModelChoiceField(
-        queryset=DeviceBay.objects.all(),
-        to_field_name='name',
-        help_text=_('Device bay in which this device is installed')
-    )
-
-    class Meta(BaseDeviceImportForm.Meta):
-        fields = [
-            'name', 'device_role', 'tenant', 'manufacturer', 'device_type', 'platform', 'serial', 'asset_tag', 'status',
-            'parent', 'device_bay', 'virtual_chassis', 'vc_position', 'vc_priority', 'cluster', 'comments', 'tags'
-        ]
-
-    def __init__(self, data=None, *args, **kwargs):
-        super().__init__(data, *args, **kwargs)
-
-        if data:
-
-            # Limit device bay queryset by parent device
-            params = {f"device__{self.fields['parent'].to_field_name}": data.get('parent')}
-            self.fields['device_bay'].queryset = self.fields['device_bay'].queryset.filter(**params)
-
-    def clean(self):
-        super().clean()
-
-        # Set parent_bay reverse relationship
-        device_bay = self.cleaned_data.get('device_bay')
-        if device_bay:
-            self.instance.parent_bay = device_bay
-
-        # Inherit site and rack from parent device
-        parent = self.cleaned_data.get('parent')
-        if parent:
-            self.instance.site = parent.site
-            self.instance.rack = parent.rack
-
-
 #
 # Device components
 #

+ 0 - 1
netbox/dcim/urls.py

@@ -177,7 +177,6 @@ urlpatterns = [
     path('devices/', views.DeviceListView.as_view(), name='device_list'),
     path('devices/add/', views.DeviceEditView.as_view(), name='device_add'),
     path('devices/import/', views.DeviceBulkImportView.as_view(), name='device_import'),
-    path('devices/import/child-devices/', views.ChildDeviceBulkImportView.as_view(), name='device_import_child'),
     path('devices/edit/', views.DeviceBulkEditView.as_view(), name='device_bulk_edit'),
     path('devices/rename/', views.DeviceBulkRenameView.as_view(), name='device_bulk_rename'),
     path('devices/delete/', views.DeviceBulkDeleteView.as_view(), name='device_bulk_delete'),

+ 5 - 12
netbox/dcim/views.py

@@ -2090,22 +2090,15 @@ class DeviceBulkImportView(generic.BulkImportView):
     queryset = Device.objects.all()
     model_form = forms.DeviceImportForm
     table = tables.DeviceImportTable
-    template_name = 'dcim/device_import.html'
-
-
-class ChildDeviceBulkImportView(generic.BulkImportView):
-    queryset = Device.objects.all()
-    model_form = forms.ChildDeviceImportForm
-    table = tables.DeviceImportTable
-    template_name = 'dcim/device_import_child.html'
 
     def save_object(self, object_form, request):
         obj = object_form.save()
 
-        # Save the reverse relation to the parent device bay
-        device_bay = obj.parent_bay
-        device_bay.installed_device = obj
-        device_bay.save()
+        # For child devices, save the reverse relation to the parent device bay
+        if getattr(obj, 'parent_bay', None):
+            device_bay = obj.parent_bay
+            device_bay.installed_device = obj
+            device_bay.save()
 
         return obj
 

+ 0 - 5
netbox/templates/dcim/device_import.html

@@ -1,5 +0,0 @@
-{% extends 'generic/bulk_import.html' %}
-
-{% block tabs %}
-  {% include 'dcim/inc/device_import_header.html' %}
-{% endblock %}

+ 0 - 5
netbox/templates/dcim/device_import_child.html

@@ -1,5 +0,0 @@
-{% extends 'generic/bulk_import.html' %}
-
-{% block tabs %}
-  {% include 'dcim/inc/device_import_header.html' with active_tab='child_import' %}
-{% endblock %}

+ 0 - 8
netbox/templates/dcim/inc/device_import_header.html

@@ -1,8 +0,0 @@
-<ul class="nav nav-tabs px-3">
-    <li class="nav-item" role="presentation">
-        <a class ="nav-link{% if not active_tab %} active{% endif %}" href="{% url 'dcim:device_import' %}">Racked Devices</a>
-    </li>
-    <li class="nav-item" role="presentation">
-        <a class="nav-link{% if active_tab == 'child_import' %} active{% endif %}" href="{% url 'dcim:device_import_child' %}">Child Devices</a>
-    </li>
-</ul>