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

Replace FilterChoiceField with DynamicModelMultipleChoiceField

This commit is contained in:
Jeremy Stretch
2020-02-11 09:26:39 -05:00
parent 5ea30c8628
commit da68968d75
8 changed files with 168 additions and 119 deletions

View File

@ -9,7 +9,7 @@ from tenancy.forms import TenancyFilterForm, TenancyForm
from tenancy.models import Tenant from tenancy.models import Tenant
from utilities.forms import ( from utilities.forms import (
APISelect, APISelectMultiple, add_blank_choice, BootstrapMixin, CommentField, CSVChoiceField, DatePicker, APISelect, APISelectMultiple, add_blank_choice, BootstrapMixin, CommentField, CSVChoiceField, DatePicker,
FilterChoiceField, SmallTextarea, SlugField, StaticSelect2, StaticSelect2Multiple, TagFilterField DynamicModelMultipleChoiceField, SmallTextarea, SlugField, StaticSelect2, StaticSelect2Multiple, TagFilterField,
) )
from .choices import CircuitStatusChoices from .choices import CircuitStatusChoices
from .models import Circuit, CircuitTermination, CircuitType, Provider from .models import Circuit, CircuitTermination, CircuitType, Provider
@ -107,7 +107,7 @@ class ProviderFilterForm(BootstrapMixin, CustomFieldFilterForm):
required=False, required=False,
label='Search' label='Search'
) )
region = FilterChoiceField( region = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(), queryset=Region.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False, required=False,
@ -119,9 +119,10 @@ class ProviderFilterForm(BootstrapMixin, CustomFieldFilterForm):
} }
) )
) )
site = FilterChoiceField( site = DynamicModelMultipleChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/sites/", api_url="/api/dcim/sites/",
value_field="slug", value_field="slug",
@ -290,17 +291,19 @@ class CircuitFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm
required=False, required=False,
label='Search' label='Search'
) )
type = FilterChoiceField( type = DynamicModelMultipleChoiceField(
queryset=CircuitType.objects.all(), queryset=CircuitType.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/circuits/circuit-types/", api_url="/api/circuits/circuit-types/",
value_field="slug", value_field="slug",
) )
) )
provider = FilterChoiceField( provider = DynamicModelMultipleChoiceField(
queryset=Provider.objects.all(), queryset=Provider.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/circuits/providers/", api_url="/api/circuits/providers/",
value_field="slug", value_field="slug",
@ -311,7 +314,7 @@ class CircuitFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm
required=False, required=False,
widget=StaticSelect2Multiple() widget=StaticSelect2Multiple()
) )
region = FilterChoiceField( region = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(), queryset=Region.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False, required=False,
@ -323,9 +326,10 @@ class CircuitFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm
} }
) )
) )
site = FilterChoiceField( site = DynamicModelMultipleChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/sites/", api_url="/api/dcim/sites/",
value_field="slug", value_field="slug",

View File

@ -23,8 +23,8 @@ from tenancy.models import Tenant, TenantGroup
from utilities.forms import ( from utilities.forms import (
APISelect, APISelectMultiple, add_blank_choice, ArrayFieldSelectMultiple, BootstrapMixin, BulkEditForm, APISelect, APISelectMultiple, add_blank_choice, ArrayFieldSelectMultiple, BootstrapMixin, BulkEditForm,
BulkEditNullBooleanSelect, ColorSelect, CommentField, ConfirmationForm, CSVChoiceField, DynamicModelChoiceField, BulkEditNullBooleanSelect, ColorSelect, CommentField, ConfirmationForm, CSVChoiceField, DynamicModelChoiceField,
ExpandableNameField, FilterChoiceField, FlexibleModelChoiceField, JSONField, SelectWithPK, SmallTextarea, SlugField, DynamicModelMultipleChoiceField, ExpandableNameField, FlexibleModelChoiceField, JSONField, SelectWithPK,
StaticSelect2, StaticSelect2Multiple, TagFilterField, BOOLEAN_WITH_BLANK_CHOICES, SmallTextarea, SlugField, StaticSelect2, StaticSelect2Multiple, TagFilterField, BOOLEAN_WITH_BLANK_CHOICES,
) )
from virtualization.models import Cluster, ClusterGroup, VirtualMachine from virtualization.models import Cluster, ClusterGroup, VirtualMachine
from .choices import * from .choices import *
@ -66,7 +66,7 @@ class DeviceComponentFilterForm(BootstrapMixin, forms.Form):
required=False, required=False,
label='Search' label='Search'
) )
region = FilterChoiceField( region = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(), queryset=Region.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False, required=False,
@ -78,9 +78,10 @@ class DeviceComponentFilterForm(BootstrapMixin, forms.Form):
} }
) )
) )
site = FilterChoiceField( site = DynamicModelMultipleChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/sites/", api_url="/api/dcim/sites/",
value_field="slug", value_field="slug",
@ -89,7 +90,7 @@ class DeviceComponentFilterForm(BootstrapMixin, forms.Form):
} }
) )
) )
device_id = FilterChoiceField( device_id = DynamicModelMultipleChoiceField(
queryset=Device.objects.all(), queryset=Device.objects.all(),
required=False, required=False,
label='Device', label='Device',
@ -369,9 +370,10 @@ class SiteFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
required=False, required=False,
widget=StaticSelect2Multiple() widget=StaticSelect2Multiple()
) )
region = FilterChoiceField( region = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(), queryset=Region.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/regions/", api_url="/api/dcim/regions/",
value_field="slug", value_field="slug",
@ -419,7 +421,7 @@ class RackGroupCSVForm(forms.ModelForm):
class RackGroupFilterForm(BootstrapMixin, forms.Form): class RackGroupFilterForm(BootstrapMixin, forms.Form):
region = FilterChoiceField( region = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(), queryset=Region.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False, required=False,
@ -431,9 +433,10 @@ class RackGroupFilterForm(BootstrapMixin, forms.Form):
} }
) )
) )
site = FilterChoiceField( site = DynamicModelMultipleChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/sites/", api_url="/api/dcim/sites/",
value_field="slug", value_field="slug",
@ -702,7 +705,7 @@ class RackFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
required=False, required=False,
label='Search' label='Search'
) )
region = FilterChoiceField( region = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(), queryset=Region.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False, required=False,
@ -714,9 +717,10 @@ class RackFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
} }
) )
) )
site = FilterChoiceField( site = DynamicModelMultipleChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/sites/", api_url="/api/dcim/sites/",
value_field="slug", value_field="slug",
@ -725,10 +729,11 @@ class RackFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
} }
) )
) )
group_id = FilterChoiceField( group_id = DynamicModelMultipleChoiceField(
queryset=RackGroup.objects.prefetch_related( queryset=RackGroup.objects.prefetch_related(
'site' 'site'
), ),
required=False,
label='Rack group', label='Rack group',
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/rack-groups/", api_url="/api/dcim/rack-groups/",
@ -740,9 +745,10 @@ class RackFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
required=False, required=False,
widget=StaticSelect2Multiple() widget=StaticSelect2Multiple()
) )
role = FilterChoiceField( role = DynamicModelMultipleChoiceField(
queryset=RackRole.objects.all(), queryset=RackRole.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/rack-roles/", api_url="/api/dcim/rack-roles/",
value_field="slug", value_field="slug",
@ -758,7 +764,7 @@ class RackFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
class RackElevationFilterForm(RackFilterForm): class RackElevationFilterForm(RackFilterForm):
field_order = ['q', 'region', 'site', 'group_id', 'id', 'status', 'role', 'tenant_group', 'tenant'] field_order = ['q', 'region', 'site', 'group_id', 'id', 'status', 'role', 'tenant_group', 'tenant']
id = FilterChoiceField( id = DynamicModelMultipleChoiceField(
queryset=Rack.objects.all(), queryset=Rack.objects.all(),
label='Rack', label='Rack',
required=False, required=False,
@ -853,16 +859,18 @@ class RackReservationFilterForm(BootstrapMixin, TenancyFilterForm):
required=False, required=False,
label='Search' label='Search'
) )
site = FilterChoiceField( site = DynamicModelMultipleChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/sites/", api_url="/api/dcim/sites/",
value_field="slug", value_field="slug",
) )
) )
group_id = FilterChoiceField( group_id = DynamicModelMultipleChoiceField(
queryset=RackGroup.objects.prefetch_related('site'), queryset=RackGroup.objects.prefetch_related('site'),
required=False,
label='Rack group', label='Rack group',
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/rack-groups/", api_url="/api/dcim/rack-groups/",
@ -968,9 +976,10 @@ class DeviceTypeFilterForm(BootstrapMixin, CustomFieldFilterForm):
required=False, required=False,
label='Search' label='Search'
) )
manufacturer = FilterChoiceField( manufacturer = DynamicModelMultipleChoiceField(
queryset=Manufacturer.objects.all(), queryset=Manufacturer.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/manufacturers/", api_url="/api/dcim/manufacturers/",
value_field="slug", value_field="slug",
@ -2123,7 +2132,7 @@ class DeviceFilterForm(BootstrapMixin, LocalConfigContextFilterForm, TenancyFilt
required=False, required=False,
label='Search' label='Search'
) )
region = FilterChoiceField( region = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(), queryset=Region.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False, required=False,
@ -2135,9 +2144,10 @@ class DeviceFilterForm(BootstrapMixin, LocalConfigContextFilterForm, TenancyFilt
} }
) )
) )
site = FilterChoiceField( site = DynamicModelMultipleChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/sites/", api_url="/api/dcim/sites/",
value_field="slug", value_field="slug",
@ -2147,10 +2157,9 @@ class DeviceFilterForm(BootstrapMixin, LocalConfigContextFilterForm, TenancyFilt
} }
) )
) )
rack_group_id = FilterChoiceField( rack_group_id = DynamicModelMultipleChoiceField(
queryset=RackGroup.objects.prefetch_related( queryset=RackGroup.objects.all(),
'site' required=False,
),
label='Rack group', label='Rack group',
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/rack-groups/", api_url="/api/dcim/rack-groups/",
@ -2159,24 +2168,27 @@ class DeviceFilterForm(BootstrapMixin, LocalConfigContextFilterForm, TenancyFilt
} }
) )
) )
rack_id = FilterChoiceField( rack_id = DynamicModelMultipleChoiceField(
queryset=Rack.objects.all(), queryset=Rack.objects.all(),
required=False,
label='Rack', label='Rack',
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/racks/", api_url="/api/dcim/racks/",
null_option=True, null_option=True,
) )
) )
role = FilterChoiceField( role = DynamicModelMultipleChoiceField(
queryset=DeviceRole.objects.all(), queryset=DeviceRole.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/device-roles/", api_url="/api/dcim/device-roles/",
value_field="slug", value_field="slug",
) )
) )
manufacturer_id = FilterChoiceField( manufacturer_id = DynamicModelMultipleChoiceField(
queryset=Manufacturer.objects.all(), queryset=Manufacturer.objects.all(),
required=False,
label='Manufacturer', label='Manufacturer',
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/manufacturers/", api_url="/api/dcim/manufacturers/",
@ -2185,19 +2197,19 @@ class DeviceFilterForm(BootstrapMixin, LocalConfigContextFilterForm, TenancyFilt
} }
) )
) )
device_type_id = FilterChoiceField( device_type_id = DynamicModelMultipleChoiceField(
queryset=DeviceType.objects.prefetch_related( queryset=DeviceType.objects.all(),
'manufacturer' required=False,
),
label='Model', label='Model',
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/device-types/", api_url="/api/dcim/device-types/",
display_field="model", display_field="model",
) )
) )
platform = FilterChoiceField( platform = DynamicModelMultipleChoiceField(
queryset=Platform.objects.all(), queryset=Platform.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/platforms/", api_url="/api/dcim/platforms/",
value_field="slug", value_field="slug",
@ -3848,9 +3860,10 @@ class CableFilterForm(BootstrapMixin, forms.Form):
required=False, required=False,
label='Search' label='Search'
) )
site = FilterChoiceField( site = DynamicModelMultipleChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/sites/", api_url="/api/dcim/sites/",
value_field="slug", value_field="slug",
@ -3860,9 +3873,10 @@ class CableFilterForm(BootstrapMixin, forms.Form):
} }
) )
) )
tenant = FilterChoiceField( tenant = DynamicModelMultipleChoiceField(
queryset=Tenant.objects.all(), queryset=Tenant.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/tenancy/tenants/", api_url="/api/tenancy/tenants/",
value_field='slug', value_field='slug',
@ -3871,8 +3885,9 @@ class CableFilterForm(BootstrapMixin, forms.Form):
} }
) )
) )
rack_id = FilterChoiceField( rack_id = DynamicModelMultipleChoiceField(
queryset=Rack.objects.all(), queryset=Rack.objects.all(),
required=False,
label='Rack', label='Rack',
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/racks/", api_url="/api/dcim/racks/",
@ -3897,7 +3912,7 @@ class CableFilterForm(BootstrapMixin, forms.Form):
required=False, required=False,
widget=ColorSelect() widget=ColorSelect()
) )
device_id = FilterChoiceField( device_id = DynamicModelMultipleChoiceField(
queryset=Device.objects.all(), queryset=Device.objects.all(),
required=False, required=False,
label='Device', label='Device',
@ -4029,9 +4044,10 @@ class DeviceBayBulkRenameForm(BulkRenameForm):
# #
class ConsoleConnectionFilterForm(BootstrapMixin, forms.Form): class ConsoleConnectionFilterForm(BootstrapMixin, forms.Form):
site = FilterChoiceField( site = DynamicModelMultipleChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/sites/", api_url="/api/dcim/sites/",
value_field="slug", value_field="slug",
@ -4040,7 +4056,7 @@ class ConsoleConnectionFilterForm(BootstrapMixin, forms.Form):
} }
) )
) )
device_id = FilterChoiceField( device_id = DynamicModelMultipleChoiceField(
queryset=Device.objects.all(), queryset=Device.objects.all(),
required=False, required=False,
label='Device', label='Device',
@ -4051,9 +4067,10 @@ class ConsoleConnectionFilterForm(BootstrapMixin, forms.Form):
class PowerConnectionFilterForm(BootstrapMixin, forms.Form): class PowerConnectionFilterForm(BootstrapMixin, forms.Form):
site = FilterChoiceField( site = DynamicModelMultipleChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/sites/", api_url="/api/dcim/sites/",
value_field="slug", value_field="slug",
@ -4062,7 +4079,7 @@ class PowerConnectionFilterForm(BootstrapMixin, forms.Form):
} }
) )
) )
device_id = FilterChoiceField( device_id = DynamicModelMultipleChoiceField(
queryset=Device.objects.all(), queryset=Device.objects.all(),
required=False, required=False,
label='Device', label='Device',
@ -4073,9 +4090,10 @@ class PowerConnectionFilterForm(BootstrapMixin, forms.Form):
class InterfaceConnectionFilterForm(BootstrapMixin, forms.Form): class InterfaceConnectionFilterForm(BootstrapMixin, forms.Form):
site = FilterChoiceField( site = DynamicModelMultipleChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/sites/", api_url="/api/dcim/sites/",
value_field="slug", value_field="slug",
@ -4084,7 +4102,7 @@ class InterfaceConnectionFilterForm(BootstrapMixin, forms.Form):
} }
) )
) )
device_id = FilterChoiceField( device_id = DynamicModelMultipleChoiceField(
queryset=Device.objects.all(), queryset=Device.objects.all(),
required=False, required=False,
label='Device', label='Device',
@ -4219,7 +4237,7 @@ class InventoryItemFilterForm(BootstrapMixin, forms.Form):
required=False, required=False,
label='Search' label='Search'
) )
region = FilterChoiceField( region = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(), queryset=Region.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False, required=False,
@ -4231,9 +4249,10 @@ class InventoryItemFilterForm(BootstrapMixin, forms.Form):
} }
) )
) )
site = FilterChoiceField( site = DynamicModelMultipleChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/sites/", api_url="/api/dcim/sites/",
value_field="slug", value_field="slug",
@ -4242,7 +4261,7 @@ class InventoryItemFilterForm(BootstrapMixin, forms.Form):
} }
) )
) )
device_id = FilterChoiceField( device_id = DynamicModelMultipleChoiceField(
queryset=Device.objects.all(), queryset=Device.objects.all(),
required=False, required=False,
label='Device', label='Device',
@ -4250,9 +4269,10 @@ class InventoryItemFilterForm(BootstrapMixin, forms.Form):
api_url='/api/dcim/devices/', api_url='/api/dcim/devices/',
) )
) )
manufacturer = FilterChoiceField( manufacturer = DynamicModelMultipleChoiceField(
queryset=Manufacturer.objects.all(), queryset=Manufacturer.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelect( widget=APISelect(
api_url="/api/dcim/manufacturers/", api_url="/api/dcim/manufacturers/",
value_field="slug", value_field="slug",
@ -4398,7 +4418,7 @@ class VirtualChassisFilterForm(BootstrapMixin, CustomFieldFilterForm):
required=False, required=False,
label='Search' label='Search'
) )
region = FilterChoiceField( region = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(), queryset=Region.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False, required=False,
@ -4410,17 +4430,19 @@ class VirtualChassisFilterForm(BootstrapMixin, CustomFieldFilterForm):
} }
) )
) )
site = FilterChoiceField( site = DynamicModelMultipleChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/sites/", api_url="/api/dcim/sites/",
value_field="slug", value_field="slug",
) )
) )
tenant_group = FilterChoiceField( tenant_group = DynamicModelMultipleChoiceField(
queryset=TenantGroup.objects.all(), queryset=TenantGroup.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/tenancy/tenant-groups/", api_url="/api/tenancy/tenant-groups/",
value_field="slug", value_field="slug",
@ -4430,9 +4452,10 @@ class VirtualChassisFilterForm(BootstrapMixin, CustomFieldFilterForm):
} }
) )
) )
tenant = FilterChoiceField( tenant = DynamicModelMultipleChoiceField(
queryset=Tenant.objects.all(), queryset=Tenant.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/tenancy/tenants/", api_url="/api/tenancy/tenants/",
value_field="slug", value_field="slug",
@ -4511,7 +4534,7 @@ class PowerPanelFilterForm(BootstrapMixin, CustomFieldFilterForm):
required=False, required=False,
label='Search' label='Search'
) )
region = FilterChoiceField( region = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(), queryset=Region.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False, required=False,
@ -4523,9 +4546,10 @@ class PowerPanelFilterForm(BootstrapMixin, CustomFieldFilterForm):
} }
) )
) )
site = FilterChoiceField( site = DynamicModelMultipleChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/sites/", api_url="/api/dcim/sites/",
value_field="slug", value_field="slug",
@ -4534,8 +4558,9 @@ class PowerPanelFilterForm(BootstrapMixin, CustomFieldFilterForm):
} }
) )
) )
rack_group_id = FilterChoiceField( rack_group_id = DynamicModelMultipleChoiceField(
queryset=RackGroup.objects.all(), queryset=RackGroup.objects.all(),
required=False,
label='Rack group (ID)', label='Rack group (ID)',
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/rack-groups/", api_url="/api/dcim/rack-groups/",
@ -4743,7 +4768,7 @@ class PowerFeedFilterForm(BootstrapMixin, CustomFieldFilterForm):
required=False, required=False,
label='Search' label='Search'
) )
region = FilterChoiceField( region = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(), queryset=Region.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False, required=False,
@ -4755,9 +4780,10 @@ class PowerFeedFilterForm(BootstrapMixin, CustomFieldFilterForm):
} }
) )
) )
site = FilterChoiceField( site = DynamicModelMultipleChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/sites/", api_url="/api/dcim/sites/",
value_field="slug", value_field="slug",
@ -4767,16 +4793,18 @@ class PowerFeedFilterForm(BootstrapMixin, CustomFieldFilterForm):
} }
) )
) )
power_panel_id = FilterChoiceField( power_panel_id = DynamicModelMultipleChoiceField(
queryset=PowerPanel.objects.all(), queryset=PowerPanel.objects.all(),
required=False,
label='Power panel', label='Power panel',
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/power-panels/", api_url="/api/dcim/power-panels/",
null_option=True, null_option=True,
) )
) )
rack_id = FilterChoiceField( rack_id = DynamicModelMultipleChoiceField(
queryset=Rack.objects.all(), queryset=Rack.objects.all(),
required=False,
label='Rack', label='Rack',
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/racks/", api_url="/api/dcim/racks/",

View File

@ -7,8 +7,8 @@ from dcim.models import DeviceRole, Platform, Region, Site
from tenancy.models import Tenant, TenantGroup from tenancy.models import Tenant, TenantGroup
from utilities.forms import ( from utilities.forms import (
add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorSelect, add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorSelect,
CommentField, ContentTypeSelect, DateTimePicker, FilterChoiceField, JSONField, SlugField, StaticSelect2, CommentField, ContentTypeSelect, DateTimePicker, DynamicModelMultipleChoiceField, JSONField, SlugField,
BOOLEAN_WITH_BLANK_CHOICES, StaticSelect2, BOOLEAN_WITH_BLANK_CHOICES,
) )
from virtualization.models import Cluster, ClusterGroup from virtualization.models import Cluster, ClusterGroup
from .choices import * from .choices import *
@ -265,72 +265,81 @@ class ConfigContextFilterForm(BootstrapMixin, forms.Form):
required=False, required=False,
label='Search' label='Search'
) )
region = FilterChoiceField( region = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(), queryset=Region.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/regions/", api_url="/api/dcim/regions/",
value_field="slug", value_field="slug",
) )
) )
site = FilterChoiceField( site = DynamicModelMultipleChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/sites/", api_url="/api/dcim/sites/",
value_field="slug", value_field="slug",
) )
) )
role = FilterChoiceField( role = DynamicModelMultipleChoiceField(
queryset=DeviceRole.objects.all(), queryset=DeviceRole.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/device-roles/", api_url="/api/dcim/device-roles/",
value_field="slug", value_field="slug",
) )
) )
platform = FilterChoiceField( platform = DynamicModelMultipleChoiceField(
queryset=Platform.objects.all(), queryset=Platform.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/platforms/", api_url="/api/dcim/platforms/",
value_field="slug", value_field="slug",
) )
) )
cluster_group = FilterChoiceField( cluster_group = DynamicModelMultipleChoiceField(
queryset=ClusterGroup.objects.all(), queryset=ClusterGroup.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/virtualization/cluster-groups/", api_url="/api/virtualization/cluster-groups/",
value_field="slug", value_field="slug",
) )
) )
cluster_id = FilterChoiceField( cluster_id = DynamicModelMultipleChoiceField(
queryset=Cluster.objects.all(), queryset=Cluster.objects.all(),
required=False,
label='Cluster', label='Cluster',
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/virtualization/clusters/", api_url="/api/virtualization/clusters/",
) )
) )
tenant_group = FilterChoiceField( tenant_group = DynamicModelMultipleChoiceField(
queryset=TenantGroup.objects.all(), queryset=TenantGroup.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/tenancy/tenant-groups/", api_url="/api/tenancy/tenant-groups/",
value_field="slug", value_field="slug",
) )
) )
tenant = FilterChoiceField( tenant = DynamicModelMultipleChoiceField(
queryset=Tenant.objects.all(), queryset=Tenant.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/tenancy/tenants/", api_url="/api/tenancy/tenants/",
value_field="slug", value_field="slug",
) )
) )
tag = FilterChoiceField( tag = DynamicModelMultipleChoiceField(
queryset=Tag.objects.all(), queryset=Tag.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/extras/tags/", api_url="/api/extras/tags/",
value_field="slug", value_field="slug",
@ -390,7 +399,7 @@ class ObjectChangeFilterForm(BootstrapMixin, forms.Form):
required=False, required=False,
widget=StaticSelect2() widget=StaticSelect2()
) )
# TODO: Convert to FilterChoiceField once we have an API endpoint for users # TODO: Convert to DynamicModelMultipleChoiceField once we have an API endpoint for users
user = forms.ModelChoiceField( user = forms.ModelChoiceField(
queryset=User.objects.order_by('username'), queryset=User.objects.order_by('username'),
required=False, required=False,

View File

@ -11,8 +11,9 @@ from tenancy.forms import TenancyFilterForm, TenancyForm
from tenancy.models import Tenant from tenancy.models import Tenant
from utilities.forms import ( from utilities.forms import (
add_blank_choice, APISelect, APISelectMultiple, BootstrapMixin, BulkEditNullBooleanSelect, CSVChoiceField, add_blank_choice, APISelect, APISelectMultiple, BootstrapMixin, BulkEditNullBooleanSelect, CSVChoiceField,
DatePicker, DynamicModelChoiceField, ExpandableIPAddressField, FilterChoiceField, FlexibleModelChoiceField, DatePicker, DynamicModelChoiceField, DynamicModelMultipleChoiceField, ExpandableIPAddressField,
ReturnURLForm, SlugField, StaticSelect2, StaticSelect2Multiple, TagFilterField, BOOLEAN_WITH_BLANK_CHOICES, FlexibleModelChoiceField, ReturnURLForm, SlugField, StaticSelect2, StaticSelect2Multiple, TagFilterField,
BOOLEAN_WITH_BLANK_CHOICES,
) )
from virtualization.models import VirtualMachine from virtualization.models import VirtualMachine
from .constants import * from .constants import *
@ -226,9 +227,10 @@ class AggregateFilterForm(BootstrapMixin, CustomFieldFilterForm):
label='Address family', label='Address family',
widget=StaticSelect2() widget=StaticSelect2()
) )
rir = FilterChoiceField( rir = DynamicModelMultipleChoiceField(
queryset=RIR.objects.all(), queryset=RIR.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
label='RIR', label='RIR',
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/ipam/rirs/", api_url="/api/ipam/rirs/",
@ -517,8 +519,9 @@ class PrefixFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm)
label='Mask length', label='Mask length',
widget=StaticSelect2() widget=StaticSelect2()
) )
vrf_id = FilterChoiceField( vrf_id = DynamicModelMultipleChoiceField(
queryset=VRF.objects.all(), queryset=VRF.objects.all(),
required=False,
label='VRF', label='VRF',
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/ipam/vrfs/", api_url="/api/ipam/vrfs/",
@ -530,7 +533,7 @@ class PrefixFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm)
required=False, required=False,
widget=StaticSelect2Multiple() widget=StaticSelect2Multiple()
) )
region = FilterChoiceField( region = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(), queryset=Region.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False, required=False,
@ -542,18 +545,20 @@ class PrefixFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm)
} }
) )
) )
site = FilterChoiceField( site = DynamicModelMultipleChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/sites/", api_url="/api/dcim/sites/",
value_field="slug", value_field="slug",
null_option=True, null_option=True,
) )
) )
role = FilterChoiceField( role = DynamicModelMultipleChoiceField(
queryset=Role.objects.all(), queryset=Role.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/ipam/roles/", api_url="/api/ipam/roles/",
value_field="slug", value_field="slug",
@ -975,8 +980,9 @@ class IPAddressFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterFo
label='Mask length', label='Mask length',
widget=StaticSelect2() widget=StaticSelect2()
) )
vrf_id = FilterChoiceField( vrf_id = DynamicModelMultipleChoiceField(
queryset=VRF.objects.all(), queryset=VRF.objects.all(),
required=False,
label='VRF', label='VRF',
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/ipam/vrfs/", api_url="/api/ipam/vrfs/",
@ -1043,7 +1049,7 @@ class VLANGroupCSVForm(forms.ModelForm):
class VLANGroupFilterForm(BootstrapMixin, forms.Form): class VLANGroupFilterForm(BootstrapMixin, forms.Form):
region = FilterChoiceField( region = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(), queryset=Region.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False, required=False,
@ -1055,9 +1061,10 @@ class VLANGroupFilterForm(BootstrapMixin, forms.Form):
} }
) )
) )
site = FilterChoiceField( site = DynamicModelMultipleChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/sites/", api_url="/api/dcim/sites/",
value_field="slug", value_field="slug",
@ -1236,7 +1243,7 @@ class VLANFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
required=False, required=False,
label='Search' label='Search'
) )
region = FilterChoiceField( region = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(), queryset=Region.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False, required=False,
@ -1249,17 +1256,19 @@ class VLANFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
} }
) )
) )
site = FilterChoiceField( site = DynamicModelMultipleChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/sites/", api_url="/api/dcim/sites/",
value_field="slug", value_field="slug",
null_option=True, null_option=True,
) )
) )
group_id = FilterChoiceField( group_id = DynamicModelMultipleChoiceField(
queryset=VLANGroup.objects.all(), queryset=VLANGroup.objects.all(),
required=False,
label='VLAN group', label='VLAN group',
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/ipam/vlan-groups/", api_url="/api/ipam/vlan-groups/",
@ -1271,9 +1280,10 @@ class VLANFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
required=False, required=False,
widget=StaticSelect2Multiple() widget=StaticSelect2Multiple()
) )
role = FilterChoiceField( role = DynamicModelMultipleChoiceField(
queryset=Role.objects.all(), queryset=Role.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/ipam/roles/", api_url="/api/ipam/roles/",
value_field="slug", value_field="slug",

View File

@ -8,7 +8,7 @@ from extras.forms import (
AddRemoveTagsForm, CustomFieldBulkEditForm, CustomFieldFilterForm, CustomFieldModelForm, CustomFieldModelCSVForm, AddRemoveTagsForm, CustomFieldBulkEditForm, CustomFieldFilterForm, CustomFieldModelForm, CustomFieldModelCSVForm,
) )
from utilities.forms import ( from utilities.forms import (
APISelect, APISelectMultiple, BootstrapMixin, FilterChoiceField, FlexibleModelChoiceField, SlugField, APISelect, APISelectMultiple, BootstrapMixin, DynamicModelMultipleChoiceField, FlexibleModelChoiceField, SlugField,
StaticSelect2Multiple, TagFilterField StaticSelect2Multiple, TagFilterField
) )
from .constants import * from .constants import *
@ -181,9 +181,10 @@ class SecretFilterForm(BootstrapMixin, CustomFieldFilterForm):
required=False, required=False,
label='Search' label='Search'
) )
role = FilterChoiceField( role = DynamicModelMultipleChoiceField(
queryset=SecretRole.objects.all(), queryset=SecretRole.objects.all(),
to_field_name='slug', to_field_name='slug',
required=True,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/secrets/secret-roles/", api_url="/api/secrets/secret-roles/",
value_field="slug", value_field="slug",

View File

@ -5,8 +5,8 @@ from extras.forms import (
AddRemoveTagsForm, CustomFieldModelForm, CustomFieldBulkEditForm, CustomFieldFilterForm, AddRemoveTagsForm, CustomFieldModelForm, CustomFieldBulkEditForm, CustomFieldFilterForm,
) )
from utilities.forms import ( from utilities.forms import (
APISelect, APISelectMultiple, BootstrapMixin, CommentField, DynamicModelChoiceField, FilterChoiceField, SlugField, APISelect, APISelectMultiple, BootstrapMixin, CommentField, DynamicModelChoiceField,
TagFilterField, DynamicModelMultipleChoiceField, SlugField, TagFilterField,
) )
from .models import Tenant, TenantGroup from .models import Tenant, TenantGroup
@ -105,9 +105,10 @@ class TenantFilterForm(BootstrapMixin, CustomFieldFilterForm):
required=False, required=False,
label='Search' label='Search'
) )
group = FilterChoiceField( group = DynamicModelMultipleChoiceField(
queryset=TenantGroup.objects.all(), queryset=TenantGroup.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/tenancy/tenant-groups/", api_url="/api/tenancy/tenant-groups/",
value_field="slug", value_field="slug",
@ -156,9 +157,10 @@ class TenancyForm(forms.Form):
class TenancyFilterForm(forms.Form): class TenancyFilterForm(forms.Form):
tenant_group = FilterChoiceField( tenant_group = DynamicModelMultipleChoiceField(
queryset=TenantGroup.objects.all(), queryset=TenantGroup.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/tenancy/tenant-groups/", api_url="/api/tenancy/tenant-groups/",
value_field="slug", value_field="slug",
@ -168,9 +170,10 @@ class TenancyFilterForm(forms.Form):
} }
) )
) )
tenant = FilterChoiceField( tenant = DynamicModelMultipleChoiceField(
queryset=Tenant.objects.all(), queryset=Tenant.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/tenancy/tenants/", api_url="/api/tenancy/tenants/",
value_field="slug", value_field="slug",

View File

@ -579,17 +579,6 @@ class DynamicModelMultipleChoiceField(DynamicModelChoiceField):
field_modifier = '__in' field_modifier = '__in'
class FilterChoiceField(DynamicModelMultipleChoiceField):
"""
A version of DynamicModelMultipleChoiceField which defaults to required=False.
"""
def __init__(self, *args, **kwargs):
# Filter fields are not required by default
if 'required' not in kwargs:
kwargs['required'] = False
super().__init__(*args, **kwargs)
class LaxURLField(forms.URLField): class LaxURLField(forms.URLField):
""" """
Modifies Django's built-in URLField in two ways: Modifies Django's built-in URLField in two ways:

View File

@ -15,8 +15,7 @@ from tenancy.models import Tenant
from utilities.forms import ( from utilities.forms import (
add_blank_choice, APISelect, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, add_blank_choice, APISelect, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect,
CommentField, ConfirmationForm, CSVChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, CommentField, ConfirmationForm, CSVChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField,
ExpandableNameField, FilterChoiceField, JSONField, SlugField, SmallTextarea, StaticSelect2, StaticSelect2Multiple, ExpandableNameField, JSONField, SlugField, SmallTextarea, StaticSelect2, StaticSelect2Multiple, TagFilterField,
TagFilterField,
) )
from .choices import * from .choices import *
from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine
@ -189,7 +188,7 @@ class ClusterFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm
'q', 'type', 'region', 'site', 'group', 'tenant_group', 'tenant' 'q', 'type', 'region', 'site', 'group', 'tenant_group', 'tenant'
] ]
q = forms.CharField(required=False, label='Search') q = forms.CharField(required=False, label='Search')
type = FilterChoiceField( type = DynamicModelMultipleChoiceField(
queryset=ClusterType.objects.all(), queryset=ClusterType.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False, required=False,
@ -198,7 +197,7 @@ class ClusterFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm
value_field='slug', value_field='slug',
) )
) )
region = FilterChoiceField( region = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(), queryset=Region.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False, required=False,
@ -210,7 +209,7 @@ class ClusterFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm
} }
) )
) )
site = FilterChoiceField( site = DynamicModelMultipleChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False, required=False,
@ -220,7 +219,7 @@ class ClusterFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm
null_option=True, null_option=True,
) )
) )
group = FilterChoiceField( group = DynamicModelMultipleChoiceField(
queryset=ClusterGroup.objects.all(), queryset=ClusterGroup.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False, required=False,
@ -544,32 +543,35 @@ class VirtualMachineFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFil
required=False, required=False,
label='Search' label='Search'
) )
cluster_group = FilterChoiceField( cluster_group = DynamicModelMultipleChoiceField(
queryset=ClusterGroup.objects.all(), queryset=ClusterGroup.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url='/api/virtualization/cluster-groups/', api_url='/api/virtualization/cluster-groups/',
value_field="slug", value_field="slug",
null_option=True, null_option=True,
) )
) )
cluster_type = FilterChoiceField( cluster_type = DynamicModelMultipleChoiceField(
queryset=ClusterType.objects.all(), queryset=ClusterType.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url='/api/virtualization/cluster-types/', api_url='/api/virtualization/cluster-types/',
value_field="slug", value_field="slug",
null_option=True, null_option=True,
) )
) )
cluster_id = FilterChoiceField( cluster_id = DynamicModelMultipleChoiceField(
queryset=Cluster.objects.all(), queryset=Cluster.objects.all(),
required=False,
label='Cluster', label='Cluster',
widget=APISelectMultiple( widget=APISelectMultiple(
api_url='/api/virtualization/clusters/', api_url='/api/virtualization/clusters/',
) )
) )
region = FilterChoiceField( region = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(), queryset=Region.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False, required=False,
@ -581,18 +583,20 @@ class VirtualMachineFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFil
} }
) )
) )
site = FilterChoiceField( site = DynamicModelMultipleChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url='/api/dcim/sites/', api_url='/api/dcim/sites/',
value_field="slug", value_field="slug",
null_option=True, null_option=True,
) )
) )
role = FilterChoiceField( role = DynamicModelMultipleChoiceField(
queryset=DeviceRole.objects.filter(vm_role=True), queryset=DeviceRole.objects.filter(vm_role=True),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url='/api/dcim/device-roles/', api_url='/api/dcim/device-roles/',
value_field="slug", value_field="slug",
@ -607,9 +611,10 @@ class VirtualMachineFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFil
required=False, required=False,
widget=StaticSelect2Multiple() widget=StaticSelect2Multiple()
) )
platform = FilterChoiceField( platform = DynamicModelMultipleChoiceField(
queryset=Platform.objects.all(), queryset=Platform.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url='/api/dcim/platforms/', api_url='/api/dcim/platforms/',
value_field="slug", value_field="slug",