diff --git a/netbox/netbox/navigation/menu.py b/netbox/netbox/navigation/menu.py index e009f62f1..1379beba5 100644 --- a/netbox/netbox/navigation/menu.py +++ b/netbox/netbox/navigation/menu.py @@ -46,7 +46,7 @@ ORGANIZATION_MENU = Menu( get_model_item('tenancy', 'contact', _('Contacts')), get_model_item('tenancy', 'contactgroup', _('Contact Groups')), get_model_item('tenancy', 'contactrole', _('Contact Roles')), - get_model_item('tenancy', 'contactassignment', _('Contact Assignments'), actions=[]), + get_model_item('tenancy', 'contactassignment', _('Contact Assignments'), actions=['import']), ), ), ), diff --git a/netbox/tenancy/forms/bulk_import.py b/netbox/tenancy/forms/bulk_import.py index f9b8accd9..0aec0e28f 100644 --- a/netbox/tenancy/forms/bulk_import.py +++ b/netbox/tenancy/forms/bulk_import.py @@ -1,9 +1,11 @@ +from django.contrib.contenttypes.models import ContentType from django.utils.translation import gettext as _ from netbox.forms import NetBoxModelImportForm from tenancy.models import * -from utilities.forms.fields import CSVModelChoiceField, SlugField +from utilities.forms.fields import CSVContentTypeField, CSVModelChoiceField, SlugField __all__ = ( + 'ContactAssignmentImportForm', 'ContactImportForm', 'ContactGroupImportForm', 'ContactRoleImportForm', @@ -81,3 +83,27 @@ class ContactImportForm(NetBoxModelImportForm): class Meta: model = Contact fields = ('name', 'title', 'phone', 'email', 'address', 'link', 'group', 'description', 'comments', 'tags') + + +class ContactAssignmentImportForm(NetBoxModelImportForm): + content_type = CSVContentTypeField( + queryset=ContentType.objects.all(), + help_text=_("One or more assigned object types") + ) + contact = CSVModelChoiceField( + queryset=Contact.objects.all(), + to_field_name='name', + help_text=_('Assigned contact') + ) + role = CSVModelChoiceField( + queryset=ContactRole.objects.all(), + to_field_name='name', + help_text=_('Assigned role') + ) + + # Remove the tags field added by NetBoxModelImportForm (unsupported by ContactAssignment) + tags = None + + class Meta: + model = ContactAssignment + fields = ('content_type', 'object_id', 'contact', 'priority', 'role') diff --git a/netbox/tenancy/urls.py b/netbox/tenancy/urls.py index 87491ea0e..ad9908c62 100644 --- a/netbox/tenancy/urls.py +++ b/netbox/tenancy/urls.py @@ -49,6 +49,7 @@ urlpatterns = [ # Contact assignments path('contact-assignments/', views.ContactAssignmentListView.as_view(), name='contactassignment_list'), path('contact-assignments/add/', views.ContactAssignmentEditView.as_view(), name='contactassignment_add'), + path('contact-assignments/import/', views.ContactAssignmentBulkImportView.as_view(), name='contactassignment_import'), path('contact-assignments/edit/', views.ContactAssignmentBulkEditView.as_view(), name='contactassignment_bulk_edit'), path('contact-assignments/delete/', views.ContactAssignmentBulkDeleteView.as_view(), name='contactassignment_bulk_delete'), path('contact-assignments//', include(get_model_urls('tenancy', 'contactassignment'))), diff --git a/netbox/tenancy/views.py b/netbox/tenancy/views.py index bbe901bde..23020e794 100644 --- a/netbox/tenancy/views.py +++ b/netbox/tenancy/views.py @@ -420,6 +420,11 @@ class ContactAssignmentBulkEditView(generic.BulkEditView): form = forms.ContactAssignmentBulkEditForm +class ContactAssignmentBulkImportView(generic.BulkImportView): + queryset = ContactAssignment.objects.all() + model_form = forms.ContactAssignmentImportForm + + class ContactAssignmentBulkDeleteView(generic.BulkDeleteView): queryset = ContactAssignment.objects.all() filterset = filtersets.ContactAssignmentFilterSet