From c35e7b8ee5e771f00150935cded4c057082b3820 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Tue, 21 Mar 2023 13:47:08 -0400 Subject: [PATCH] #11584: Add bulk edit view & tests --- netbox/tenancy/forms/bulk_edit.py | 25 +++++++- netbox/tenancy/tests/test_views.py | 91 ++++++++++++++++++++++++++++++ netbox/tenancy/urls.py | 1 + netbox/tenancy/views.py | 8 ++- 4 files changed, 123 insertions(+), 2 deletions(-) diff --git a/netbox/tenancy/forms/bulk_edit.py b/netbox/tenancy/forms/bulk_edit.py index ab882fe7e..ae30d93ff 100644 --- a/netbox/tenancy/forms/bulk_edit.py +++ b/netbox/tenancy/forms/bulk_edit.py @@ -1,10 +1,12 @@ from django import forms from netbox.forms import NetBoxModelBulkEditForm +from tenancy.choices import ContactPriorityChoices from tenancy.models import * -from utilities.forms import CommentField, DynamicModelChoiceField +from utilities.forms import CommentField, DynamicModelChoiceField, add_blank_choice __all__ = ( + 'ContactAssignmentBulkEditForm', 'ContactBulkEditForm', 'ContactGroupBulkEditForm', 'ContactRoleBulkEditForm', @@ -114,3 +116,24 @@ class ContactBulkEditForm(NetBoxModelBulkEditForm): (None, ('group', 'title', 'phone', 'email', 'address', 'link', 'description')), ) nullable_fields = ('group', 'title', 'phone', 'email', 'address', 'link', 'description', 'comments') + + +class ContactAssignmentBulkEditForm(NetBoxModelBulkEditForm): + contact = DynamicModelChoiceField( + queryset=Contact.objects.all(), + required=False + ) + role = DynamicModelChoiceField( + queryset=ContactRole.objects.all(), + required=False + ) + priority = forms.ChoiceField( + choices=add_blank_choice(ContactPriorityChoices), + required=False + ) + + model = ContactAssignment + fieldsets = ( + (None, ('contact', 'role', 'priority')), + ) + nullable_fields = ('priority',) diff --git a/netbox/tenancy/tests/test_views.py b/netbox/tenancy/tests/test_views.py index 0ac5b16d4..2151a6e8b 100644 --- a/netbox/tenancy/tests/test_views.py +++ b/netbox/tenancy/tests/test_views.py @@ -1,3 +1,8 @@ +from django.contrib.contenttypes.models import ContentType +from django.urls import reverse + +from dcim.models import Site +from tenancy.choices import ContactPriorityChoices from tenancy.models import * from utilities.testing import ViewTestCases, create_tags @@ -223,3 +228,89 @@ class ContactTestCase(ViewTestCases.PrimaryObjectViewTestCase): cls.bulk_edit_data = { 'group': contact_groups[1].pk, } + + +class ContactAssignmentTestCase( + ViewTestCases.CreateObjectViewTestCase, + ViewTestCases.EditObjectViewTestCase, + ViewTestCases.DeleteObjectViewTestCase, + ViewTestCases.ListObjectsViewTestCase, + ViewTestCases.BulkEditObjectsViewTestCase, + ViewTestCases.BulkDeleteObjectsViewTestCase +): + model = ContactAssignment + + @classmethod + def setUpTestData(cls): + + sites = ( + Site(name='Site 1', slug='site-1'), + Site(name='Site 2', slug='site-2'), + Site(name='Site 3', slug='site-3'), + Site(name='Site 4', slug='site-4'), + ) + Site.objects.bulk_create(sites) + + contacts = ( + Contact(name='Contact 1'), + Contact(name='Contact 2'), + Contact(name='Contact 3'), + Contact(name='Contact 4'), + ) + Contact.objects.bulk_create(contacts) + + contact_roles = ( + ContactRole(name='Contact Role 1', slug='contact-role-1'), + ContactRole(name='Contact Role 2', slug='contact-role-2'), + ContactRole(name='Contact Role 3', slug='contact-role-3'), + ContactRole(name='Contact Role 4', slug='contact-role-4'), + ) + ContactRole.objects.bulk_create(contact_roles) + + assignments = ( + ContactAssignment( + object=sites[0], + contact=contacts[0], + role=contact_roles[0], + priority=ContactPriorityChoices.PRIORITY_PRIMARY + ), + ContactAssignment( + object=sites[1], + contact=contacts[1], + role=contact_roles[1], + priority=ContactPriorityChoices.PRIORITY_SECONDARY + ), + ContactAssignment( + object=sites[2], + contact=contacts[2], + role=contact_roles[2], + priority=ContactPriorityChoices.PRIORITY_TERTIARY + ), + ) + ContactAssignment.objects.bulk_create(assignments) + + tags = create_tags('Alpha', 'Bravo', 'Charlie') + + cls.form_data = { + 'content_type': ContentType.objects.get_for_model(Site).pk, + 'object_id': sites[3].pk, + 'contact': contacts[3].pk, + 'role': contact_roles[3].pk, + 'priority': ContactPriorityChoices.PRIORITY_INACTIVE, + 'tags': [t.pk for t in tags], + } + + cls.bulk_edit_data = { + 'role': contact_roles[3].pk, + 'priority': ContactPriorityChoices.PRIORITY_INACTIVE, + } + + def _get_url(self, action, instance=None): + # Override creation URL to append content_type & object_id parameters + if action == 'add': + url = reverse('tenancy:contactassignment_add') + content_type = ContentType.objects.get_for_model(Site).pk + object_id = Site.objects.first().pk + return f"{url}?content_type={content_type}&object_id={object_id}" + + return super()._get_url(action, instance=instance) diff --git a/netbox/tenancy/urls.py b/netbox/tenancy/urls.py index 6563eff4b..87491ea0e 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/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 6248ddddf..2a0fe19b5 100644 --- a/netbox/tenancy/views.py +++ b/netbox/tenancy/views.py @@ -349,7 +349,6 @@ class ContactAssignmentListView(generic.ObjectListView): filterset = filtersets.ContactAssignmentFilterSet filterset_form = forms.ContactAssignmentFilterForm table = tables.ContactAssignmentTable - actions = ('export', 'bulk_delete') @register_model_view(ContactAssignment, 'edit') @@ -372,6 +371,13 @@ class ContactAssignmentEditView(generic.ObjectEditView): } +class ContactAssignmentBulkEditView(generic.BulkEditView): + queryset = ContactAssignment.objects.all() + filterset = filtersets.ContactAssignmentFilterSet + table = tables.ContactAssignmentTable + form = forms.ContactAssignmentBulkEditForm + + class ContactAssignmentBulkDeleteView(generic.BulkDeleteView): queryset = ContactAssignment.objects.all() filterset = filtersets.ContactAssignmentFilterSet