Просмотр исходного кода

#4416: Add bulk_add view for InventoryItems

Jeremy Stretch 5 лет назад
Родитель
Сommit
e4b5045ec7
5 измененных файлов с 175 добавлено и 149 удалено
  1. 159 149
      netbox/dcim/forms.py
  2. 1 0
      netbox/dcim/urls.py
  3. 11 0
      netbox/dcim/views.py
  4. 3 0
      netbox/templates/dcim/device.html
  5. 1 0
      netbox/templates/dcim/device_list.html

+ 159 - 149
netbox/dcim/forms.py

@@ -3372,6 +3372,165 @@ class DeviceBayCSVForm(CSVModelForm):
             self.fields['installed_device'].queryset = Interface.objects.none()
             self.fields['installed_device'].queryset = Interface.objects.none()
 
 
 
 
+#
+# Inventory items
+#
+
+class InventoryItemForm(BootstrapMixin, forms.ModelForm):
+    device = DynamicModelChoiceField(
+        queryset=Device.objects.prefetch_related('device_type__manufacturer')
+    )
+    manufacturer = DynamicModelChoiceField(
+        queryset=Manufacturer.objects.all(),
+        required=False
+    )
+    tags = DynamicModelMultipleChoiceField(
+        queryset=Tag.objects.all(),
+        required=False
+    )
+
+    class Meta:
+        model = InventoryItem
+        fields = [
+            'name', 'device', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description', 'tags',
+        ]
+
+
+class InventoryItemCreateForm(BootstrapMixin, forms.Form):
+    device = DynamicModelChoiceField(
+        queryset=Device.objects.prefetch_related('device_type__manufacturer')
+    )
+    name_pattern = ExpandableNameField(
+        label='Name'
+    )
+    manufacturer = DynamicModelChoiceField(
+        queryset=Manufacturer.objects.all(),
+        required=False
+    )
+    part_id = forms.CharField(
+        max_length=50,
+        required=False,
+        label='Part ID'
+    )
+    serial = forms.CharField(
+        max_length=50,
+        required=False,
+    )
+    asset_tag = forms.CharField(
+        max_length=50,
+        required=False,
+    )
+    description = forms.CharField(
+        max_length=100,
+        required=False
+    )
+
+
+class InventoryItemCSVForm(CSVModelForm):
+    device = CSVModelChoiceField(
+        queryset=Device.objects.all(),
+        to_field_name='name'
+    )
+    manufacturer = CSVModelChoiceField(
+        queryset=Manufacturer.objects.all(),
+        to_field_name='name',
+        required=False
+    )
+
+    class Meta:
+        model = InventoryItem
+        fields = InventoryItem.csv_headers
+
+
+class InventoryItemBulkCreateForm(
+    form_from_model(InventoryItem, ['manufacturer', 'part_id', 'serial', 'asset_tag', 'discovered', 'tags']),
+    DeviceBulkAddComponentForm
+):
+    tags = DynamicModelMultipleChoiceField(
+        queryset=Tag.objects.all(),
+        required=False
+    )
+
+
+class InventoryItemBulkEditForm(BootstrapMixin, BulkEditForm):
+    pk = forms.ModelMultipleChoiceField(
+        queryset=InventoryItem.objects.all(),
+        widget=forms.MultipleHiddenInput()
+    )
+    device = DynamicModelChoiceField(
+        queryset=Device.objects.all(),
+        required=False
+    )
+    manufacturer = DynamicModelChoiceField(
+        queryset=Manufacturer.objects.all(),
+        required=False
+    )
+    part_id = forms.CharField(
+        max_length=50,
+        required=False,
+        label='Part ID'
+    )
+    description = forms.CharField(
+        max_length=100,
+        required=False
+    )
+
+    class Meta:
+        nullable_fields = [
+            'manufacturer', 'part_id', 'description',
+        ]
+
+
+class InventoryItemFilterForm(BootstrapMixin, forms.Form):
+    model = InventoryItem
+    q = forms.CharField(
+        required=False,
+        label='Search'
+    )
+    region = DynamicModelMultipleChoiceField(
+        queryset=Region.objects.all(),
+        to_field_name='slug',
+        required=False,
+        widget=APISelectMultiple(
+            value_field="slug",
+            filter_for={
+                'site': 'region'
+            }
+        )
+    )
+    site = DynamicModelMultipleChoiceField(
+        queryset=Site.objects.all(),
+        to_field_name='slug',
+        required=False,
+        widget=APISelectMultiple(
+            value_field="slug",
+            filter_for={
+                'device_id': 'site'
+            }
+        )
+    )
+    device_id = DynamicModelMultipleChoiceField(
+        queryset=Device.objects.all(),
+        required=False,
+        label='Device'
+    )
+    manufacturer = DynamicModelMultipleChoiceField(
+        queryset=Manufacturer.objects.all(),
+        to_field_name='slug',
+        required=False,
+        widget=APISelect(
+            value_field="slug",
+        )
+    )
+    discovered = forms.NullBooleanField(
+        required=False,
+        widget=StaticSelect2(
+            choices=BOOLEAN_WITH_BLANK_CHOICES
+        )
+    )
+    tag = TagFilterField(model)
+
+
 #
 #
 # Cables
 # Cables
 #
 #
@@ -3919,155 +4078,6 @@ class InterfaceConnectionFilterForm(BootstrapMixin, forms.Form):
     )
     )
 
 
 
 
-#
-# Inventory items
-#
-
-class InventoryItemForm(BootstrapMixin, forms.ModelForm):
-    device = DynamicModelChoiceField(
-        queryset=Device.objects.prefetch_related('device_type__manufacturer')
-    )
-    manufacturer = DynamicModelChoiceField(
-        queryset=Manufacturer.objects.all(),
-        required=False
-    )
-    tags = DynamicModelMultipleChoiceField(
-        queryset=Tag.objects.all(),
-        required=False
-    )
-
-    class Meta:
-        model = InventoryItem
-        fields = [
-            'name', 'device', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description', 'tags',
-        ]
-
-
-class InventoryItemCreateForm(BootstrapMixin, forms.Form):
-    device = DynamicModelChoiceField(
-        queryset=Device.objects.prefetch_related('device_type__manufacturer')
-    )
-    name_pattern = ExpandableNameField(
-        label='Name'
-    )
-    manufacturer = DynamicModelChoiceField(
-        queryset=Manufacturer.objects.all(),
-        required=False
-    )
-    part_id = forms.CharField(
-        max_length=50,
-        required=False,
-        label='Part ID'
-    )
-    serial = forms.CharField(
-        max_length=50,
-        required=False,
-    )
-    asset_tag = forms.CharField(
-        max_length=50,
-        required=False,
-    )
-    description = forms.CharField(
-        max_length=100,
-        required=False
-    )
-
-
-class InventoryItemCSVForm(CSVModelForm):
-    device = CSVModelChoiceField(
-        queryset=Device.objects.all(),
-        to_field_name='name'
-    )
-    manufacturer = CSVModelChoiceField(
-        queryset=Manufacturer.objects.all(),
-        to_field_name='name',
-        required=False
-    )
-
-    class Meta:
-        model = InventoryItem
-        fields = InventoryItem.csv_headers
-
-
-class InventoryItemBulkEditForm(BootstrapMixin, BulkEditForm):
-    pk = forms.ModelMultipleChoiceField(
-        queryset=InventoryItem.objects.all(),
-        widget=forms.MultipleHiddenInput()
-    )
-    device = DynamicModelChoiceField(
-        queryset=Device.objects.all(),
-        required=False
-    )
-    manufacturer = DynamicModelChoiceField(
-        queryset=Manufacturer.objects.all(),
-        required=False
-    )
-    part_id = forms.CharField(
-        max_length=50,
-        required=False,
-        label='Part ID'
-    )
-    description = forms.CharField(
-        max_length=100,
-        required=False
-    )
-
-    class Meta:
-        nullable_fields = [
-            'manufacturer', 'part_id', 'description',
-        ]
-
-
-class InventoryItemFilterForm(BootstrapMixin, forms.Form):
-    model = InventoryItem
-    q = forms.CharField(
-        required=False,
-        label='Search'
-    )
-    region = DynamicModelMultipleChoiceField(
-        queryset=Region.objects.all(),
-        to_field_name='slug',
-        required=False,
-        widget=APISelectMultiple(
-            value_field="slug",
-            filter_for={
-                'site': 'region'
-            }
-        )
-    )
-    site = DynamicModelMultipleChoiceField(
-        queryset=Site.objects.all(),
-        to_field_name='slug',
-        required=False,
-        widget=APISelectMultiple(
-            value_field="slug",
-            filter_for={
-                'device_id': 'site'
-            }
-        )
-    )
-    device_id = DynamicModelMultipleChoiceField(
-        queryset=Device.objects.all(),
-        required=False,
-        label='Device'
-    )
-    manufacturer = DynamicModelMultipleChoiceField(
-        queryset=Manufacturer.objects.all(),
-        to_field_name='slug',
-        required=False,
-        widget=APISelect(
-            value_field="slug",
-        )
-    )
-    discovered = forms.NullBooleanField(
-        required=False,
-        widget=StaticSelect2(
-            choices=BOOLEAN_WITH_BLANK_CHOICES
-        )
-    )
-    tag = TagFilterField(model)
-
-
 #
 #
 # Virtual chassis
 # Virtual chassis
 #
 #

+ 1 - 0
netbox/dcim/urls.py

@@ -326,6 +326,7 @@ urlpatterns = [
     path('inventory-items/<int:pk>/edit/', views.InventoryItemEditView.as_view(), name='inventoryitem_edit'),
     path('inventory-items/<int:pk>/edit/', views.InventoryItemEditView.as_view(), name='inventoryitem_edit'),
     path('inventory-items/<int:pk>/delete/', views.InventoryItemDeleteView.as_view(), name='inventoryitem_delete'),
     path('inventory-items/<int:pk>/delete/', views.InventoryItemDeleteView.as_view(), name='inventoryitem_delete'),
     path('inventory-items/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='inventoryitem_changelog', kwargs={'model': InventoryItem}),
     path('inventory-items/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='inventoryitem_changelog', kwargs={'model': InventoryItem}),
+    path('devices/inventory-items/add/', views.DeviceBulkAddInventoryItemView.as_view(), name='device_bulk_add_inventoryitem'),
 
 
     # Cables
     # Cables
     path('cables/', views.CableListView.as_view(), name='cable_list'),
     path('cables/', views.CableListView.as_view(), name='cable_list'),

+ 11 - 0
netbox/dcim/views.py

@@ -1859,6 +1859,17 @@ class DeviceBulkAddDeviceBayView(BulkComponentCreateView):
     default_return_url = 'dcim:device_list'
     default_return_url = 'dcim:device_list'
 
 
 
 
+class DeviceBulkAddInventoryItemView(BulkComponentCreateView):
+    parent_model = Device
+    parent_field = 'device'
+    form = forms.InventoryItemBulkCreateForm
+    queryset = InventoryItem.objects.all()
+    model_form = forms.InventoryItemForm
+    filterset = filters.DeviceFilterSet
+    table = tables.DeviceTable
+    default_return_url = 'dcim:device_list'
+
+
 #
 #
 # Cables
 # Cables
 #
 #

+ 3 - 0
netbox/templates/dcim/device.html

@@ -74,6 +74,9 @@
                     {% if perms.dcim.add_devicebay %}
                     {% if perms.dcim.add_devicebay %}
                         <li><a href="{% url 'dcim:devicebay_add' %}?device={{ device.pk }}&return_url={{ device.get_absolute_url }}">Device Bays</a></li>
                         <li><a href="{% url 'dcim:devicebay_add' %}?device={{ device.pk }}&return_url={{ device.get_absolute_url }}">Device Bays</a></li>
                     {% endif %}
                     {% endif %}
+                    {% if perms.dcim.add_inventoryitem %}
+                        <li><a href="{% url 'dcim:inventoryitem_add' %}?device={{ device.pk }}&return_url={{ device.get_absolute_url }}">Inventory Items</a></li>
+                    {% endif %}
                 </ul>
                 </ul>
             </div>
             </div>
         {% endif %}
         {% endif %}

+ 1 - 0
netbox/templates/dcim/device_list.html

@@ -14,6 +14,7 @@
                 {% if perms.dcim.add_interface %}<li><a href="{% url 'dcim:device_bulk_add_interface' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="formaction">Interfaces</a></li>{% endif %}
                 {% if perms.dcim.add_interface %}<li><a href="{% url 'dcim:device_bulk_add_interface' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="formaction">Interfaces</a></li>{% endif %}
                 {% if perms.dcim.add_rearport %}<li><a href="{% url 'dcim:device_bulk_add_rearport' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="formaction">Rear Ports</a></li>{% endif %}
                 {% if perms.dcim.add_rearport %}<li><a href="{% url 'dcim:device_bulk_add_rearport' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="formaction">Rear Ports</a></li>{% endif %}
                 {% if perms.dcim.add_devicebay %}<li><a href="{% url 'dcim:device_bulk_add_devicebay' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="formaction">Device Bays</a></li>{% endif %}
                 {% if perms.dcim.add_devicebay %}<li><a href="{% url 'dcim:device_bulk_add_devicebay' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="formaction">Device Bays</a></li>{% endif %}
+                {% if perms.dcim.add_inventoryitem %}<li><a href="{% url 'dcim:device_bulk_add_inventoryitem' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="formaction">Inventory Items</a></li>{% endif %}
             </ul>
             </ul>
         </div>
         </div>
     {% endif %}
     {% endif %}