From fd2bcda8b8777b955222644a5ff94417ba510cb2 Mon Sep 17 00:00:00 2001 From: Jason Novinger Date: Wed, 26 Mar 2025 12:12:45 -0500 Subject: [PATCH] Fixes #18991: AttributeError: NoneType object has not attribute model (#19006) --- netbox/dcim/tests/test_api.py | 40 ++++++++++++++++++++++++++++++++++- netbox/utilities/fields.py | 4 ++-- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/netbox/dcim/tests/test_api.py b/netbox/dcim/tests/test_api.py index 08f93f6ea..b1ed4aca3 100644 --- a/netbox/dcim/tests/test_api.py +++ b/netbox/dcim/tests/test_api.py @@ -1,6 +1,6 @@ import json -from django.test import override_settings +from django.test import override_settings, tag from django.urls import reverse from django.utils.translation import gettext as _ from rest_framework import status @@ -1904,6 +1904,27 @@ class FrontPortTest(APIViewTestCases.APIViewTestCase): }, ] + @tag('regression') # Issue #18991 + def test_front_port_paths(self): + device = Device.objects.first() + rear_port = RearPort.objects.create( + device=device, name='Rear Port 10', type=PortTypeChoices.TYPE_8P8C + ) + interface1 = Interface.objects.create(device=device, name='Interface 1') + front_port = FrontPort.objects.create( + device=device, + name='Rear Port 10', + type=PortTypeChoices.TYPE_8P8C, + rear_port=rear_port, + ) + Cable.objects.create(a_terminations=[interface1], b_terminations=[front_port]) + + self.add_permissions(f'dcim.view_{self.model._meta.model_name}') + url = reverse(f'dcim-api:{self.model._meta.model_name}-paths', kwargs={'pk': front_port.pk}) + response = self.client.get(url, **self.header) + + self.assertHttpStatus(response, status.HTTP_200_OK) + class RearPortTest(APIViewTestCases.APIViewTestCase): model = RearPort @@ -1947,6 +1968,23 @@ class RearPortTest(APIViewTestCases.APIViewTestCase): }, ] + @tag('regression') # Issue #18991 + def test_rear_port_paths(self): + device = Device.objects.first() + interface1 = Interface.objects.create(device=device, name='Interface 1') + rear_port = RearPort.objects.create( + device=device, + name='Rear Port 10', + type=PortTypeChoices.TYPE_8P8C, + ) + Cable.objects.create(a_terminations=[interface1], b_terminations=[rear_port]) + + self.add_permissions(f'dcim.view_{self.model._meta.model_name}') + url = reverse(f'dcim-api:{self.model._meta.model_name}-paths', kwargs={'pk': rear_port.pk}) + response = self.client.get(url, **self.header) + + self.assertHttpStatus(response, status.HTTP_200_OK) + class ModuleBayTest(APIViewTestCases.APIViewTestCase): model = ModuleBay diff --git a/netbox/utilities/fields.py b/netbox/utilities/fields.py index 05f61a147..e2814465a 100644 --- a/netbox/utilities/fields.py +++ b/netbox/utilities/fields.py @@ -198,9 +198,9 @@ class GenericArrayForeignKey(FieldCacheMixin, models.Field): Provide a generic many-to-many relation through an 2d array field """ - many_to_many = True + many_to_many = False many_to_one = False - one_to_many = False + one_to_many = True one_to_one = False def __init__(self, field, for_concrete_model=True):