Fixes: #14058 - Limits platform selection to manufacturer and platforms with no manufacturer (#15183)

* Fixes: #14058 - Limits platform selection to manufacturer and platforms with no manufacturer

* Apply suggestions from code review

Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>

---------

Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
This commit is contained in:
Daniel Sheppard 2024-02-20 08:28:15 -06:00 committed by GitHub
parent bd7d4a3f34
commit 29f029d480
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 35 additions and 2 deletions

View File

@ -2,6 +2,8 @@ import django_filters
from django.contrib.auth import get_user_model
from django.contrib.contenttypes.models import ContentType
from django.utils.translation import gettext as _
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import extend_schema_field
from circuits.models import CircuitTermination
from extras.filtersets import LocalConfigContextFilterSet
@ -818,6 +820,10 @@ class PlatformFilterSet(OrganizationalModelFilterSet):
to_field_name='slug',
label=_('Manufacturer (slug)'),
)
available_for_device_type = django_filters.ModelChoiceFilter(
queryset=DeviceType.objects.all(),
method='get_for_device_type'
)
config_template_id = django_filters.ModelMultipleChoiceFilter(
queryset=ConfigTemplate.objects.all(),
label=_('Config template (ID)'),
@ -827,6 +833,14 @@ class PlatformFilterSet(OrganizationalModelFilterSet):
model = Platform
fields = ['id', 'name', 'slug', 'description']
@extend_schema_field(OpenApiTypes.STR)
def get_for_device_type(self, queryset, name, value):
"""
Return all Platforms available for a specific manufacturer based on device type and Platforms not assigned any
manufacturer
"""
return queryset.filter(Q(manufacturer=None) | Q(manufacturer__device_types=value))
class DeviceFilterSet(
NetBoxModelFilterSet,

View File

@ -291,7 +291,11 @@ class DeviceTypeForm(NetBoxModelForm):
default_platform = DynamicModelChoiceField(
label=_('Default platform'),
queryset=Platform.objects.all(),
required=False
required=False,
selector=True,
query_params={
'manufacturer_id': ['$manufacturer', 'null'],
}
)
slug = SlugField(
label=_('Slug'),
@ -444,7 +448,10 @@ class DeviceForm(TenancyForm, NetBoxModelForm):
label=_('Platform'),
queryset=Platform.objects.all(),
required=False,
selector=True
selector=True,
query_params={
'available_for_device_type': '$device_type',
}
)
cluster = DynamicModelChoiceField(
label=_('Cluster'),

View File

@ -1787,6 +1787,7 @@ class PlatformTestCase(TestCase, ChangeLoggedFilterSetTests):
Platform(name='Platform 1', slug='platform-1', manufacturer=manufacturers[0], description='foobar1'),
Platform(name='Platform 2', slug='platform-2', manufacturer=manufacturers[1], description='foobar2'),
Platform(name='Platform 3', slug='platform-3', manufacturer=manufacturers[2], description='foobar3'),
Platform(name='Platform 4', slug='platform-4'),
)
Platform.objects.bulk_create(platforms)
@ -1813,6 +1814,17 @@ class PlatformTestCase(TestCase, ChangeLoggedFilterSetTests):
params = {'manufacturer': [manufacturers[0].slug, manufacturers[1].slug]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_available_for_device_type(self):
manufacturers = Manufacturer.objects.all()[:2]
device_type = DeviceType.objects.create(
manufacturer=manufacturers[0],
model='Device Type 1',
slug='device-type-1',
u_height=1
)
params = {'available_for_device_type': device_type.pk}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
class DeviceTestCase(TestCase, ChangeLoggedFilterSetTests):
queryset = Device.objects.all()