1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Introduce local ChoiceField and MultipleChoiceField classes

This commit is contained in:
jeremystretch
2022-03-21 15:08:05 -04:00
parent ba1e6e91b9
commit 3dc671395e
8 changed files with 108 additions and 114 deletions

View File

@ -35,6 +35,16 @@ In addition to the [form fields provided by Django](https://docs.djangoproject.c
selection: selection:
members: false members: false
## Choice Fields
::: utilities.forms.ChoiceField
selection:
members: false
::: utilities.forms.MultipleChoiceField
selection:
members: false
## Dynamic Object Fields ## Dynamic Object Fields
::: utilities.forms.DynamicModelChoiceField ::: utilities.forms.DynamicModelChoiceField

View File

@ -6,7 +6,7 @@ from circuits.models import *
from dcim.models import Region, Site, SiteGroup from dcim.models import Region, Site, SiteGroup
from netbox.forms import NetBoxModelFilterSetForm from netbox.forms import NetBoxModelFilterSetForm
from tenancy.forms import TenancyFilterForm, ContactModelFilterForm from tenancy.forms import TenancyFilterForm, ContactModelFilterForm
from utilities.forms import DynamicModelMultipleChoiceField, StaticSelectMultiple, TagFilterField from utilities.forms import DynamicModelMultipleChoiceField, MultipleChoiceField, TagFilterField
__all__ = ( __all__ = (
'CircuitFilterForm', 'CircuitFilterForm',
@ -101,10 +101,9 @@ class CircuitFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFi
}, },
label=_('Provider network') label=_('Provider network')
) )
status = forms.MultipleChoiceField( status = MultipleChoiceField(
choices=CircuitStatusChoices, choices=CircuitStatusChoices,
required=False, required=False
widget=StaticSelectMultiple()
) )
region_id = DynamicModelMultipleChoiceField( region_id = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(), queryset=Region.objects.all(),

View File

@ -10,8 +10,8 @@ from ipam.models import ASN, VRF
from netbox.forms import NetBoxModelFilterSetForm from netbox.forms import NetBoxModelFilterSetForm
from tenancy.forms import ContactModelFilterForm, TenancyFilterForm from tenancy.forms import ContactModelFilterForm, TenancyFilterForm
from utilities.forms import ( from utilities.forms import (
APISelectMultiple, add_blank_choice, ColorField, DynamicModelMultipleChoiceField, FilterForm, StaticSelect, APISelectMultiple, add_blank_choice, ColorField, DynamicModelMultipleChoiceField, FilterForm, MultipleChoiceField,
StaticSelectMultiple, TagFilterField, BOOLEAN_WITH_BLANK_CHOICES, SelectSpeedWidget, StaticSelect, TagFilterField, BOOLEAN_WITH_BLANK_CHOICES, SelectSpeedWidget,
) )
from wireless.choices import * from wireless.choices import *
@ -140,10 +140,9 @@ class SiteFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFilte
('Tenant', ('tenant_group_id', 'tenant_id')), ('Tenant', ('tenant_group_id', 'tenant_id')),
('Contacts', ('contact', 'contact_role')), ('Contacts', ('contact', 'contact_role')),
) )
status = forms.MultipleChoiceField( status = MultipleChoiceField(
choices=SiteStatusChoices, choices=SiteStatusChoices,
required=False, required=False
widget=StaticSelectMultiple(),
) )
region_id = DynamicModelMultipleChoiceField( region_id = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(), queryset=Region.objects.all(),
@ -239,20 +238,17 @@ class RackFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFilte
}, },
label=_('Location') label=_('Location')
) )
status = forms.MultipleChoiceField( status = MultipleChoiceField(
choices=RackStatusChoices, choices=RackStatusChoices,
required=False, required=False
widget=StaticSelectMultiple()
) )
type = forms.MultipleChoiceField( type = MultipleChoiceField(
choices=RackTypeChoices, choices=RackTypeChoices,
required=False, required=False
widget=StaticSelectMultiple()
) )
width = forms.MultipleChoiceField( width = MultipleChoiceField(
choices=RackWidthChoices, choices=RackWidthChoices,
required=False, required=False
widget=StaticSelectMultiple()
) )
role_id = DynamicModelMultipleChoiceField( role_id = DynamicModelMultipleChoiceField(
queryset=RackRole.objects.all(), queryset=RackRole.objects.all(),
@ -346,15 +342,13 @@ class DeviceTypeFilterForm(NetBoxModelFilterSetForm):
part_number = forms.CharField( part_number = forms.CharField(
required=False required=False
) )
subdevice_role = forms.MultipleChoiceField( subdevice_role = MultipleChoiceField(
choices=add_blank_choice(SubdeviceRoleChoices), choices=add_blank_choice(SubdeviceRoleChoices),
required=False, required=False
widget=StaticSelectMultiple()
) )
airflow = forms.MultipleChoiceField( airflow = MultipleChoiceField(
choices=add_blank_choice(DeviceAirflowChoices), choices=add_blank_choice(DeviceAirflowChoices),
required=False, required=False
widget=StaticSelectMultiple()
) )
console_ports = forms.NullBooleanField( console_ports = forms.NullBooleanField(
required=False, required=False,
@ -561,15 +555,13 @@ class DeviceFilterForm(
null_option='None', null_option='None',
label=_('Platform') label=_('Platform')
) )
status = forms.MultipleChoiceField( status = MultipleChoiceField(
choices=DeviceStatusChoices, choices=DeviceStatusChoices,
required=False, required=False
widget=StaticSelectMultiple()
) )
airflow = forms.MultipleChoiceField( airflow = MultipleChoiceField(
choices=add_blank_choice(DeviceAirflowChoices), choices=add_blank_choice(DeviceAirflowChoices),
required=False, required=False
widget=StaticSelectMultiple()
) )
serial = forms.CharField( serial = forms.CharField(
required=False required=False
@ -739,15 +731,13 @@ class CableFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
}, },
label=_('Device') label=_('Device')
) )
type = forms.MultipleChoiceField( type = MultipleChoiceField(
choices=add_blank_choice(CableTypeChoices), choices=add_blank_choice(CableTypeChoices),
required=False, required=False
widget=StaticSelect()
) )
status = forms.ChoiceField( status = MultipleChoiceField(
required=False, required=False,
choices=add_blank_choice(LinkStatusChoices), choices=add_blank_choice(LinkStatusChoices)
widget=StaticSelect()
) )
color = ColorField( color = ColorField(
required=False required=False
@ -843,10 +833,9 @@ class PowerFeedFilterForm(NetBoxModelFilterSetForm):
}, },
label=_('Rack') label=_('Rack')
) )
status = forms.MultipleChoiceField( status = MultipleChoiceField(
choices=PowerFeedStatusChoices, choices=PowerFeedStatusChoices,
required=False, required=False
widget=StaticSelectMultiple()
) )
type = forms.ChoiceField( type = forms.ChoiceField(
choices=add_blank_choice(PowerFeedTypeChoices), choices=add_blank_choice(PowerFeedTypeChoices),
@ -886,15 +875,13 @@ class ConsolePortFilterForm(DeviceComponentFilterForm):
('Attributes', ('name', 'label', 'type', 'speed')), ('Attributes', ('name', 'label', 'type', 'speed')),
('Device', ('region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id')), ('Device', ('region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id')),
) )
type = forms.MultipleChoiceField( type = MultipleChoiceField(
choices=ConsolePortTypeChoices, choices=ConsolePortTypeChoices,
required=False, required=False
widget=StaticSelectMultiple()
) )
speed = forms.MultipleChoiceField( speed = MultipleChoiceField(
choices=ConsolePortSpeedChoices, choices=ConsolePortSpeedChoices,
required=False, required=False
widget=StaticSelectMultiple()
) )
tag = TagFilterField(model) tag = TagFilterField(model)
@ -906,15 +893,13 @@ class ConsoleServerPortFilterForm(DeviceComponentFilterForm):
('Attributes', ('name', 'label', 'type', 'speed')), ('Attributes', ('name', 'label', 'type', 'speed')),
('Device', ('region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id')), ('Device', ('region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id')),
) )
type = forms.MultipleChoiceField( type = MultipleChoiceField(
choices=ConsolePortTypeChoices, choices=ConsolePortTypeChoices,
required=False, required=False
widget=StaticSelectMultiple()
) )
speed = forms.MultipleChoiceField( speed = MultipleChoiceField(
choices=ConsolePortSpeedChoices, choices=ConsolePortSpeedChoices,
required=False, required=False
widget=StaticSelectMultiple()
) )
tag = TagFilterField(model) tag = TagFilterField(model)
@ -926,10 +911,9 @@ class PowerPortFilterForm(DeviceComponentFilterForm):
('Attributes', ('name', 'label', 'type')), ('Attributes', ('name', 'label', 'type')),
('Device', ('region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id')), ('Device', ('region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id')),
) )
type = forms.MultipleChoiceField( type = MultipleChoiceField(
choices=PowerPortTypeChoices, choices=PowerPortTypeChoices,
required=False, required=False
widget=StaticSelectMultiple()
) )
tag = TagFilterField(model) tag = TagFilterField(model)
@ -941,10 +925,9 @@ class PowerOutletFilterForm(DeviceComponentFilterForm):
('Attributes', ('name', 'label', 'type')), ('Attributes', ('name', 'label', 'type')),
('Device', ('region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id')), ('Device', ('region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id')),
) )
type = forms.MultipleChoiceField( type = MultipleChoiceField(
choices=PowerOutletTypeChoices, choices=PowerOutletTypeChoices,
required=False, required=False
widget=StaticSelectMultiple()
) )
tag = TagFilterField(model) tag = TagFilterField(model)
@ -958,26 +941,22 @@ class InterfaceFilterForm(DeviceComponentFilterForm):
('Wireless', ('rf_role', 'rf_channel', 'rf_channel_width', 'tx_power')), ('Wireless', ('rf_role', 'rf_channel', 'rf_channel_width', 'tx_power')),
('Device', ('region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id')), ('Device', ('region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id')),
) )
kind = forms.MultipleChoiceField( kind = MultipleChoiceField(
choices=InterfaceKindChoices, choices=InterfaceKindChoices,
required=False, required=False
widget=StaticSelectMultiple()
) )
type = forms.MultipleChoiceField( type = MultipleChoiceField(
choices=InterfaceTypeChoices, choices=InterfaceTypeChoices,
required=False, required=False
widget=StaticSelectMultiple()
) )
speed = forms.IntegerField( speed = forms.IntegerField(
required=False, required=False,
label='Select Speed', label='Select Speed',
widget=SelectSpeedWidget(attrs={'readonly': None}) widget=SelectSpeedWidget(attrs={'readonly': None})
) )
duplex = forms.MultipleChoiceField( duplex = MultipleChoiceField(
choices=InterfaceDuplexChoices, choices=InterfaceDuplexChoices,
required=False, required=False
label='Select Duplex',
widget=StaticSelectMultiple()
) )
enabled = forms.NullBooleanField( enabled = forms.NullBooleanField(
required=False, required=False,
@ -999,16 +978,14 @@ class InterfaceFilterForm(DeviceComponentFilterForm):
required=False, required=False,
label='WWN' label='WWN'
) )
rf_role = forms.MultipleChoiceField( rf_role = MultipleChoiceField(
choices=WirelessRoleChoices, choices=WirelessRoleChoices,
required=False, required=False,
widget=StaticSelectMultiple(),
label='Wireless role' label='Wireless role'
) )
rf_channel = forms.MultipleChoiceField( rf_channel = MultipleChoiceField(
choices=WirelessChannelChoices, choices=WirelessChannelChoices,
required=False, required=False,
widget=StaticSelectMultiple(),
label='Wireless channel' label='Wireless channel'
) )
rf_channel_frequency = forms.IntegerField( rf_channel_frequency = forms.IntegerField(
@ -1040,10 +1017,9 @@ class FrontPortFilterForm(DeviceComponentFilterForm):
('Device', ('region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id')), ('Device', ('region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id')),
) )
model = FrontPort model = FrontPort
type = forms.MultipleChoiceField( type = MultipleChoiceField(
choices=PortTypeChoices, choices=PortTypeChoices,
required=False, required=False
widget=StaticSelectMultiple()
) )
color = ColorField( color = ColorField(
required=False required=False
@ -1058,10 +1034,9 @@ class RearPortFilterForm(DeviceComponentFilterForm):
('Attributes', ('name', 'label', 'type', 'color')), ('Attributes', ('name', 'label', 'type', 'color')),
('Device', ('region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id')), ('Device', ('region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id')),
) )
type = forms.MultipleChoiceField( type = MultipleChoiceField(
choices=PortTypeChoices, choices=PortTypeChoices,
required=False, required=False
widget=StaticSelectMultiple()
) )
color = ColorField( color = ColorField(
required=False required=False

View File

@ -10,7 +10,7 @@ from extras.utils import FeatureQuery
from tenancy.models import Tenant, TenantGroup from tenancy.models import Tenant, TenantGroup
from utilities.forms import ( from utilities.forms import (
add_blank_choice, APISelectMultiple, ContentTypeChoiceField, ContentTypeMultipleChoiceField, DateTimePicker, add_blank_choice, APISelectMultiple, ContentTypeChoiceField, ContentTypeMultipleChoiceField, DateTimePicker,
DynamicModelMultipleChoiceField, FilterForm, StaticSelect, StaticSelectMultiple, BOOLEAN_WITH_BLANK_CHOICES, DynamicModelMultipleChoiceField, FilterForm, MultipleChoiceField, StaticSelect, BOOLEAN_WITH_BLANK_CHOICES,
) )
from virtualization.models import Cluster, ClusterGroup, ClusterType from virtualization.models import Cluster, ClusterGroup, ClusterType
@ -37,10 +37,9 @@ class CustomFieldFilterForm(FilterForm):
limit_choices_to=FeatureQuery('custom_fields'), limit_choices_to=FeatureQuery('custom_fields'),
required=False required=False
) )
type = forms.MultipleChoiceField( type = MultipleChoiceField(
choices=CustomFieldTypeChoices, choices=CustomFieldTypeChoices,
required=False, required=False,
widget=StaticSelectMultiple(),
label=_('Field type') label=_('Field type')
) )
weight = forms.IntegerField( weight = forms.IntegerField(
@ -117,10 +116,9 @@ class WebhookFilterForm(FilterForm):
limit_choices_to=FeatureQuery('webhooks'), limit_choices_to=FeatureQuery('webhooks'),
required=False required=False
) )
http_method = forms.MultipleChoiceField( http_method = MultipleChoiceField(
choices=WebhookHttpMethodChoices, choices=WebhookHttpMethodChoices,
required=False, required=False,
widget=StaticSelectMultiple(),
label=_('HTTP method') label=_('HTTP method')
) )
enabled = forms.NullBooleanField( enabled = forms.NullBooleanField(

View File

@ -9,7 +9,7 @@ from ipam.models import ASN
from netbox.forms import NetBoxModelFilterSetForm from netbox.forms import NetBoxModelFilterSetForm
from tenancy.forms import TenancyFilterForm from tenancy.forms import TenancyFilterForm
from utilities.forms import ( from utilities.forms import (
add_blank_choice, DynamicModelChoiceField, DynamicModelMultipleChoiceField, StaticSelect, StaticSelectMultiple, add_blank_choice, DynamicModelChoiceField, DynamicModelMultipleChoiceField, MultipleChoiceField, StaticSelect,
TagFilterField, BOOLEAN_WITH_BLANK_CHOICES, TagFilterField, BOOLEAN_WITH_BLANK_CHOICES,
) )
@ -164,11 +164,10 @@ class PrefixFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
label=_('Address family'), label=_('Address family'),
widget=StaticSelect() widget=StaticSelect()
) )
mask_length = forms.MultipleChoiceField( mask_length = MultipleChoiceField(
required=False, required=False,
choices=PREFIX_MASK_LENGTH_CHOICES, choices=PREFIX_MASK_LENGTH_CHOICES,
label=_('Mask length'), label=_('Mask length')
widget=StaticSelectMultiple()
) )
vrf_id = DynamicModelMultipleChoiceField( vrf_id = DynamicModelMultipleChoiceField(
queryset=VRF.objects.all(), queryset=VRF.objects.all(),
@ -181,10 +180,9 @@ class PrefixFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
required=False, required=False,
label=_('Present in VRF') label=_('Present in VRF')
) )
status = forms.MultipleChoiceField( status = MultipleChoiceField(
choices=PrefixStatusChoices, choices=PrefixStatusChoices,
required=False, required=False
widget=StaticSelectMultiple()
) )
region_id = DynamicModelMultipleChoiceField( region_id = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(), queryset=Region.objects.all(),
@ -247,10 +245,9 @@ class IPRangeFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
label=_('Assigned VRF'), label=_('Assigned VRF'),
null_option='Global' null_option='Global'
) )
status = forms.MultipleChoiceField( status = MultipleChoiceField(
choices=PrefixStatusChoices, choices=PrefixStatusChoices,
required=False, required=False
widget=StaticSelectMultiple()
) )
role_id = DynamicModelMultipleChoiceField( role_id = DynamicModelMultipleChoiceField(
queryset=Role.objects.all(), queryset=Role.objects.all(),
@ -301,15 +298,13 @@ class IPAddressFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
required=False, required=False,
label=_('Present in VRF') label=_('Present in VRF')
) )
status = forms.MultipleChoiceField( status = MultipleChoiceField(
choices=IPAddressStatusChoices, choices=IPAddressStatusChoices,
required=False, required=False
widget=StaticSelectMultiple()
) )
role = forms.MultipleChoiceField( role = MultipleChoiceField(
choices=IPAddressRoleChoices, choices=IPAddressRoleChoices,
required=False, required=False
widget=StaticSelectMultiple()
) )
assigned_to_interface = forms.NullBooleanField( assigned_to_interface = forms.NullBooleanField(
required=False, required=False,
@ -328,20 +323,18 @@ class FHRPGroupFilterForm(NetBoxModelFilterSetForm):
('Attributes', ('protocol', 'group_id')), ('Attributes', ('protocol', 'group_id')),
('Authentication', ('auth_type', 'auth_key')), ('Authentication', ('auth_type', 'auth_key')),
) )
protocol = forms.MultipleChoiceField( protocol = MultipleChoiceField(
choices=FHRPGroupProtocolChoices, choices=FHRPGroupProtocolChoices,
required=False, required=False
widget=StaticSelectMultiple()
) )
group_id = forms.IntegerField( group_id = forms.IntegerField(
min_value=0, min_value=0,
required=False, required=False,
label='Group ID' label='Group ID'
) )
auth_type = forms.MultipleChoiceField( auth_type = MultipleChoiceField(
choices=FHRPGroupAuthTypeChoices, choices=FHRPGroupAuthTypeChoices,
required=False, required=False,
widget=StaticSelectMultiple(),
label='Authentication type' label='Authentication type'
) )
auth_key = forms.CharField( auth_key = forms.CharField(
@ -430,10 +423,9 @@ class VLANFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
}, },
label=_('VLAN group') label=_('VLAN group')
) )
status = forms.MultipleChoiceField( status = MultipleChoiceField(
choices=VLANStatusChoices, choices=VLANStatusChoices,
required=False, required=False
widget=StaticSelectMultiple()
) )
role_id = DynamicModelMultipleChoiceField( role_id = DynamicModelMultipleChoiceField(
queryset=Role.objects.all(), queryset=Role.objects.all(),
@ -457,7 +449,7 @@ class ServiceTemplateFilterForm(NetBoxModelFilterSetForm):
protocol = forms.ChoiceField( protocol = forms.ChoiceField(
choices=add_blank_choice(ServiceProtocolChoices), choices=add_blank_choice(ServiceProtocolChoices),
required=False, required=False,
widget=StaticSelectMultiple() widget=StaticSelect()
) )
port = forms.IntegerField( port = forms.IntegerField(
required=False, required=False,

View File

@ -9,11 +9,13 @@ from utilities.forms import widgets
from utilities.validators import EnhancedURLValidator from utilities.validators import EnhancedURLValidator
__all__ = ( __all__ = (
'ChoiceField',
'ColorField', 'ColorField',
'CommentField', 'CommentField',
'JSONField', 'JSONField',
'LaxURLField', 'LaxURLField',
'MACAddressField', 'MACAddressField',
'MultipleChoiceField',
'SlugField', 'SlugField',
'TagFilterField', 'TagFilterField',
) )
@ -125,3 +127,21 @@ class MACAddressField(forms.Field):
raise forms.ValidationError(self.error_messages['invalid'], code='invalid') raise forms.ValidationError(self.error_messages['invalid'], code='invalid')
return value return value
#
# Choice fields
#
class ChoiceField(forms.ChoiceField):
"""
Overrides Django's built-in `ChoiceField` to use NetBox's `StaticSelect` widget
"""
widget = widgets.StaticSelect
class MultipleChoiceField(forms.MultipleChoiceField):
"""
Overrides Django's built-in `MultipleChoiceField` to use NetBox's `StaticSelectMultiple` widget
"""
widget = widgets.StaticSelectMultiple

View File

@ -88,9 +88,10 @@ class StaticSelect(forms.Select):
class StaticSelectMultiple(StaticSelect, forms.SelectMultiple): class StaticSelectMultiple(StaticSelect, forms.SelectMultiple):
"""
def __init__(self, *args, **kwargs): Extends `StaticSelect` to support multiple selections.
super().__init__(*args, **kwargs) """
pass
class SelectWithPK(StaticSelect): class SelectWithPK(StaticSelect):

View File

@ -7,7 +7,7 @@ from ipam.models import VRF
from netbox.forms import NetBoxModelFilterSetForm from netbox.forms import NetBoxModelFilterSetForm
from tenancy.forms import ContactModelFilterForm, TenancyFilterForm from tenancy.forms import ContactModelFilterForm, TenancyFilterForm
from utilities.forms import ( from utilities.forms import (
DynamicModelMultipleChoiceField, StaticSelect, StaticSelectMultiple, TagFilterField, BOOLEAN_WITH_BLANK_CHOICES, DynamicModelMultipleChoiceField, MultipleChoiceField, StaticSelect, TagFilterField, BOOLEAN_WITH_BLANK_CHOICES,
) )
from virtualization.choices import * from virtualization.choices import *
from virtualization.models import * from virtualization.models import *
@ -135,10 +135,9 @@ class VirtualMachineFilterForm(
}, },
label=_('Role') label=_('Role')
) )
status = forms.MultipleChoiceField( status = MultipleChoiceField(
choices=VirtualMachineStatusChoices, choices=VirtualMachineStatusChoices,
required=False, required=False
widget=StaticSelectMultiple()
) )
platform_id = DynamicModelMultipleChoiceField( platform_id = DynamicModelMultipleChoiceField(
queryset=Platform.objects.all(), queryset=Platform.objects.all(),