#4416: Add bulk_add view for InventoryItems

This commit is contained in:
Jeremy Stretch 2020-07-01 14:55:11 -04:00
parent 7e3e18faea
commit e4b5045ec7
5 changed files with 175 additions and 149 deletions

View File

@ -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
# #

View File

@ -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'),

View File

@ -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
# #

View File

@ -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 %}

View File

@ -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 %}