diff --git a/netbox/tenancy/filtersets.py b/netbox/tenancy/filtersets.py index 39e278cf5..a34accf3a 100644 --- a/netbox/tenancy/filtersets.py +++ b/netbox/tenancy/filtersets.py @@ -46,6 +46,11 @@ class ContactGroupFilterSet(OrganizationalModelFilterSet): to_field_name='slug', label=_('Contact group (slug)'), ) + contact_id = django_filters.ModelMultipleChoiceFilter( + field_name='contact', + queryset=Contact.objects.all(), + label=_('Contact (ID)'), + ) class Meta: model = ContactGroup @@ -60,13 +65,13 @@ class ContactRoleFilterSet(OrganizationalModelFilterSet): class ContactFilterSet(NetBoxModelFilterSet): - group_id = TreeNodeMultipleChoiceFilter( + contact_group_id = TreeNodeMultipleChoiceFilter( queryset=ContactGroup.objects.all(), field_name='groups', lookup_expr='in', label=_('Contact group (ID)'), ) - group = TreeNodeMultipleChoiceFilter( + contact_group = TreeNodeMultipleChoiceFilter( queryset=ContactGroup.objects.all(), field_name='groups', to_field_name='slug', diff --git a/netbox/tenancy/forms/filtersets.py b/netbox/tenancy/forms/filtersets.py index 960ca45b1..75db01770 100644 --- a/netbox/tenancy/forms/filtersets.py +++ b/netbox/tenancy/forms/filtersets.py @@ -71,7 +71,7 @@ class ContactRoleFilterForm(NetBoxModelFilterSetForm): class ContactFilterForm(NetBoxModelFilterSetForm): model = Contact - group_id = DynamicModelMultipleChoiceField( + contact_group_id = DynamicModelMultipleChoiceField( queryset=ContactGroup.objects.all(), required=False, null_option='None', diff --git a/netbox/tenancy/migrations/0018_contact_groups.py b/netbox/tenancy/migrations/0018_contact_groups.py index 38be33d09..2fcbc48de 100644 --- a/netbox/tenancy/migrations/0018_contact_groups.py +++ b/netbox/tenancy/migrations/0018_contact_groups.py @@ -66,4 +66,29 @@ class Migration(migrations.Migration): blank=True, related_name='contacts', through='tenancy.ContactGroupMembership', to='tenancy.contactgroup' ), ), + migrations.AlterField( + model_name='contactgroupmembership', + name='contact', + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='+', to='tenancy.contact' + ), + ), + migrations.AlterField( + model_name='contactgroupmembership', + name='group', + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='+', to='tenancy.contactgroup' + ), + ), + migrations.AlterField( + model_name='contact', + name='groups', + field=models.ManyToManyField( + blank=True, + related_name='contacts', + related_query_name='contact', + through='tenancy.ContactGroupMembership', + to='tenancy.contactgroup', + ), + ), ] diff --git a/netbox/tenancy/models/contacts.py b/netbox/tenancy/models/contacts.py index 28f7dc5d4..7108d0e5b 100644 --- a/netbox/tenancy/models/contacts.py +++ b/netbox/tenancy/models/contacts.py @@ -51,6 +51,7 @@ class Contact(PrimaryModel): to='tenancy.ContactGroup', related_name='contacts', through='tenancy.ContactGroupMembership', + related_query_name='contact', blank=True ) name = models.CharField( @@ -96,8 +97,8 @@ class Contact(PrimaryModel): class ContactGroupMembership(models.Model): - group = models.ForeignKey(ContactGroup, on_delete=models.CASCADE) - contact = models.ForeignKey(Contact, on_delete=models.CASCADE) + group = models.ForeignKey(ContactGroup, related_name="+", on_delete=models.CASCADE) + contact = models.ForeignKey(Contact, related_name="+", on_delete=models.CASCADE) class Meta: constraints = [ diff --git a/netbox/tenancy/tests/test_filtersets.py b/netbox/tenancy/tests/test_filtersets.py index 4d75607ba..ff88f8e10 100644 --- a/netbox/tenancy/tests/test_filtersets.py +++ b/netbox/tenancy/tests/test_filtersets.py @@ -277,9 +277,9 @@ class ContactTestCase(TestCase, ChangeLoggedFilterSetTests): def test_group(self): group = ContactGroup.objects.all()[:2] - params = {'group_id': [group[0].pk, group[1].pk]} + params = {'contact_group_id': [group[0].pk, group[1].pk]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) - params = {'group': [group[0].slug, group[1].slug]} + params = {'contact_group': [group[0].slug, group[1].slug]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) diff --git a/netbox/utilities/testing/filtersets.py b/netbox/utilities/testing/filtersets.py index e58123f03..0b3d4b198 100644 --- a/netbox/utilities/testing/filtersets.py +++ b/netbox/utilities/testing/filtersets.py @@ -144,8 +144,8 @@ class BaseFilterSetTests: # Check that the filter class is correct filter = filters[filter_name] if filter_class is not None: - self.assertIs( - type(filter), + self.assertIsInstance( + filter, filter_class, f"Invalid filter class {type(filter)} for {filter_name} (should be {filter_class})!" )