mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-14 09:51:22 -06:00
Closes #4324: Add CSV import view for services
This commit is contained in:
parent
2a5bf2a222
commit
9fa5004a35
@ -3,6 +3,7 @@
|
|||||||
## Enhancements
|
## Enhancements
|
||||||
|
|
||||||
* [#4323](https://github.com/netbox-community/netbox/issues/4323) - Add bulk edit view for power panels
|
* [#4323](https://github.com/netbox-community/netbox/issues/4323) - Add bulk edit view for power panels
|
||||||
|
* [#4324](https://github.com/netbox-community/netbox/issues/4324) - Add CSV import view for services
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -1382,6 +1382,37 @@ class ServiceFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
tag = TagFilterField(model)
|
tag = TagFilterField(model)
|
||||||
|
|
||||||
|
|
||||||
|
class ServiceCSVForm(CustomFieldModelCSVForm):
|
||||||
|
device = FlexibleModelChoiceField(
|
||||||
|
queryset=Device.objects.all(),
|
||||||
|
required=False,
|
||||||
|
to_field_name='name',
|
||||||
|
help_text='Name or ID of device',
|
||||||
|
error_messages={
|
||||||
|
'invalid_choice': 'Device not found.',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
virtual_machine = FlexibleModelChoiceField(
|
||||||
|
queryset=VirtualMachine.objects.all(),
|
||||||
|
required=False,
|
||||||
|
to_field_name='name',
|
||||||
|
help_text='Name or ID of virtual machine',
|
||||||
|
error_messages={
|
||||||
|
'invalid_choice': 'Virtual machine not found.',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
protocol = CSVChoiceField(
|
||||||
|
choices=ServiceProtocolChoices,
|
||||||
|
help_text='IP protocol'
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Service
|
||||||
|
fields = Service.csv_headers
|
||||||
|
help_texts = {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class ServiceBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
|
class ServiceBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
|
||||||
pk = forms.ModelMultipleChoiceField(
|
pk = forms.ModelMultipleChoiceField(
|
||||||
queryset=Service.objects.all(),
|
queryset=Service.objects.all(),
|
||||||
|
@ -1027,7 +1027,7 @@ class Service(ChangeLoggedModel, CustomFieldModel):
|
|||||||
|
|
||||||
tags = TaggableManager(through=TaggedItem)
|
tags = TaggableManager(through=TaggedItem)
|
||||||
|
|
||||||
csv_headers = ['device', 'virtual_machine', 'name', 'protocol', 'description']
|
csv_headers = ['device', 'virtual_machine', 'name', 'protocol', 'port', 'description']
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ('protocol', 'port', 'pk') # (protocol, port) may be non-unique
|
ordering = ('protocol', 'port', 'pk') # (protocol, port) may be non-unique
|
||||||
|
@ -334,9 +334,6 @@ class VLANTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|||||||
class ServiceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
class ServiceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
||||||
model = Service
|
model = Service
|
||||||
|
|
||||||
# Disable inapplicable tests
|
|
||||||
test_import_objects = None
|
|
||||||
|
|
||||||
# TODO: Resolve URL for Service creation
|
# TODO: Resolve URL for Service creation
|
||||||
test_create_object = None
|
test_create_object = None
|
||||||
|
|
||||||
@ -366,6 +363,13 @@ class ServiceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|||||||
'tags': 'Alpha,Bravo,Charlie',
|
'tags': 'Alpha,Bravo,Charlie',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cls.csv_data = (
|
||||||
|
"device,name,protocol,port,description",
|
||||||
|
"Device 1,Service 1,TCP,1,First service",
|
||||||
|
"Device 1,Service 2,TCP,2,Second service",
|
||||||
|
"Device 1,Service 3,UDP,3,Third service",
|
||||||
|
)
|
||||||
|
|
||||||
cls.bulk_edit_data = {
|
cls.bulk_edit_data = {
|
||||||
'protocol': ServiceProtocolChoices.PROTOCOL_UDP,
|
'protocol': ServiceProtocolChoices.PROTOCOL_UDP,
|
||||||
'port': 888,
|
'port': 888,
|
||||||
|
@ -94,6 +94,7 @@ urlpatterns = [
|
|||||||
|
|
||||||
# Services
|
# Services
|
||||||
path('services/', views.ServiceListView.as_view(), name='service_list'),
|
path('services/', views.ServiceListView.as_view(), name='service_list'),
|
||||||
|
path('services/import/', views.ServiceBulkImportView.as_view(), name='service_import'),
|
||||||
path('services/edit/', views.ServiceBulkEditView.as_view(), name='service_bulk_edit'),
|
path('services/edit/', views.ServiceBulkEditView.as_view(), name='service_bulk_edit'),
|
||||||
path('services/delete/', views.ServiceBulkDeleteView.as_view(), name='service_bulk_delete'),
|
path('services/delete/', views.ServiceBulkDeleteView.as_view(), name='service_bulk_delete'),
|
||||||
path('services/<int:pk>/', views.ServiceView.as_view(), name='service'),
|
path('services/<int:pk>/', views.ServiceView.as_view(), name='service'),
|
||||||
|
@ -1015,6 +1015,13 @@ class ServiceCreateView(PermissionRequiredMixin, ObjectEditView):
|
|||||||
return service.parent.get_absolute_url()
|
return service.parent.get_absolute_url()
|
||||||
|
|
||||||
|
|
||||||
|
class ServiceBulkImportView(PermissionRequiredMixin, BulkImportView):
|
||||||
|
permission_required = 'ipam.add_service'
|
||||||
|
model_form = forms.ServiceCSVForm
|
||||||
|
table = tables.ServiceTable
|
||||||
|
default_return_url = 'ipam:service_list'
|
||||||
|
|
||||||
|
|
||||||
class ServiceEditView(ServiceCreateView):
|
class ServiceEditView(ServiceCreateView):
|
||||||
permission_required = 'ipam.change_service'
|
permission_required = 'ipam.change_service'
|
||||||
|
|
||||||
|
@ -338,6 +338,11 @@
|
|||||||
<li class="divider"></li>
|
<li class="divider"></li>
|
||||||
<li class="dropdown-header">Services</li>
|
<li class="dropdown-header">Services</li>
|
||||||
<li{% if not perms.ipam.view_service %} class="disabled"{% endif %}>
|
<li{% if not perms.ipam.view_service %} class="disabled"{% endif %}>
|
||||||
|
{% if perms.ipam.add_vservice %}
|
||||||
|
<div class="buttons pull-right">
|
||||||
|
<a href="{% url 'ipam:service_import' %}" class="btn btn-xs btn-info" title="Import"><i class="fa fa-download"></i></a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
<a href="{% url 'ipam:service_list' %}">Services</a>
|
<a href="{% url 'ipam:service_list' %}">Services</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
Loading…
Reference in New Issue
Block a user