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

Use DynamicModelChoiceField for all fields using APISelect

This commit is contained in:
Jeremy Stretch
2020-02-11 10:43:22 -05:00
parent fb56d5bc66
commit 7177fcfa61
8 changed files with 363 additions and 246 deletions

View File

@ -9,7 +9,8 @@ from tenancy.forms import TenancyFilterForm, TenancyForm
from tenancy.models import Tenant
from utilities.forms import (
APISelect, APISelectMultiple, add_blank_choice, BootstrapMixin, CommentField, CSVChoiceField, DatePicker,
DynamicModelMultipleChoiceField, SmallTextarea, SlugField, StaticSelect2, StaticSelect2Multiple, TagFilterField,
DynamicModelChoiceField, DynamicModelMultipleChoiceField, SmallTextarea, SlugField, StaticSelect2,
StaticSelect2Multiple, TagFilterField,
)
from .choices import CircuitStatusChoices
from .models import Circuit, CircuitTermination, CircuitType, Provider
@ -165,6 +166,18 @@ class CircuitTypeCSVForm(forms.ModelForm):
#
class CircuitForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
provider = DynamicModelChoiceField(
queryset=Provider.objects.all(),
widget=APISelect(
api_url="/api/circuits/providers/"
)
)
type = DynamicModelChoiceField(
queryset=CircuitType.objects.all(),
widget=APISelect(
api_url="/api/circuits/circuit-types/"
)
)
comments = CommentField()
tags = TagField(
required=False
@ -181,12 +194,6 @@ class CircuitForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
'commit_rate': "Committed rate",
}
widgets = {
'provider': APISelect(
api_url="/api/circuits/providers/"
),
'type': APISelect(
api_url="/api/circuits/circuit-types/"
),
'status': StaticSelect2(),
'install_date': DatePicker(),
}
@ -236,14 +243,14 @@ class CircuitBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEdit
queryset=Circuit.objects.all(),
widget=forms.MultipleHiddenInput
)
type = forms.ModelChoiceField(
type = DynamicModelChoiceField(
queryset=CircuitType.objects.all(),
required=False,
widget=APISelect(
api_url="/api/circuits/circuit-types/"
)
)
provider = forms.ModelChoiceField(
provider = DynamicModelChoiceField(
queryset=Provider.objects.all(),
required=False,
widget=APISelect(
@ -256,7 +263,7 @@ class CircuitBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEdit
initial='',
widget=StaticSelect2()
)
tenant = forms.ModelChoiceField(
tenant = DynamicModelChoiceField(
queryset=Tenant.objects.all(),
required=False,
widget=APISelect(

View File

@ -325,7 +325,7 @@ class SiteBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditFor
required=False,
widget=StaticSelect2()
)
tenant = forms.ModelChoiceField(
tenant = DynamicModelChoiceField(
queryset=Tenant.objects.all(),
required=False,
widget=APISelect(
@ -383,18 +383,20 @@ class SiteFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
#
class RackGroupForm(BootstrapMixin, forms.ModelForm):
site = DynamicModelChoiceField(
queryset=Site.objects.all(),
required=False,
widget=APISelect(
api_url="/api/dcim/sites/"
)
)
slug = SlugField()
class Meta:
model = RackGroup
fields = [
fields = (
'site', 'name', 'slug',
]
widgets = {
'site': APISelect(
api_url="/api/dcim/sites/"
)
}
class RackGroupCSVForm(forms.ModelForm):
@ -471,6 +473,15 @@ class RackRoleCSVForm(forms.ModelForm):
#
class RackForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
site = DynamicModelChoiceField(
queryset=Site.objects.all(),
widget=APISelect(
api_url="/api/dcim/sites/",
filter_for={
'group': 'site_id',
}
)
)
group = DynamicModelChoiceField(
queryset=RackGroup.objects.all(),
required=False,
@ -478,6 +489,13 @@ class RackForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
api_url='/api/dcim/rack-groups/',
)
)
role = DynamicModelChoiceField(
queryset=RackRole.objects.all(),
required=False,
widget=APISelect(
api_url='/api/dcim/rack-roles/',
)
)
comments = CommentField()
tags = TagField(
required=False
@ -496,16 +514,7 @@ class RackForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
'u_height': "Height in rack units",
}
widgets = {
'site': APISelect(
api_url="/api/dcim/sites/",
filter_for={
'group': 'site_id',
}
),
'status': StaticSelect2(),
'role': APISelect(
api_url="/api/dcim/rack-roles/"
),
'type': StaticSelect2(),
'width': StaticSelect2(),
'outer_unit': StaticSelect2(),
@ -605,7 +614,7 @@ class RackBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditFor
queryset=Rack.objects.all(),
widget=forms.MultipleHiddenInput
)
site = forms.ModelChoiceField(
site = DynamicModelChoiceField(
queryset=Site.objects.all(),
required=False,
widget=APISelect(
@ -615,14 +624,14 @@ class RackBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditFor
}
)
)
group = forms.ModelChoiceField(
group = DynamicModelChoiceField(
queryset=RackGroup.objects.all(),
required=False,
widget=APISelect(
api_url="/api/dcim/rack-groups",
)
)
tenant = forms.ModelChoiceField(
tenant = DynamicModelChoiceField(
queryset=Tenant.objects.all(),
required=False,
widget=APISelect(
@ -635,7 +644,7 @@ class RackBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditFor
initial='',
widget=StaticSelect2()
)
role = forms.ModelChoiceField(
role = DynamicModelChoiceField(
queryset=RackRole.objects.all(),
required=False,
widget=APISelect(
@ -833,7 +842,7 @@ class RackReservationBulkEditForm(BootstrapMixin, BulkEditForm):
required=False,
widget=StaticSelect2()
)
tenant = forms.ModelChoiceField(
tenant = DynamicModelChoiceField(
queryset=Tenant.objects.all(),
required=False,
widget=APISelect(
@ -905,6 +914,12 @@ class ManufacturerCSVForm(forms.ModelForm):
#
class DeviceTypeForm(BootstrapMixin, CustomFieldModelForm):
manufacturer = DynamicModelChoiceField(
queryset=Manufacturer.objects.all(),
widget=APISelect(
api_url="/api/dcim/manufacturers/",
)
)
slug = SlugField(
slug_source='model'
)
@ -920,9 +935,6 @@ class DeviceTypeForm(BootstrapMixin, CustomFieldModelForm):
'tags',
]
widgets = {
'manufacturer': APISelect(
api_url="/api/dcim/manufacturers/"
),
'subdevice_role': StaticSelect2()
}
@ -945,11 +957,11 @@ class DeviceTypeBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkE
queryset=DeviceType.objects.all(),
widget=forms.MultipleHiddenInput()
)
manufacturer = forms.ModelChoiceField(
manufacturer = DynamicModelChoiceField(
queryset=Manufacturer.objects.all(),
required=False,
widget=APISelect(
api_url="/api/dcim/manufactureres"
api_url="/api/dcim/manufacturers"
)
)
u_height = forms.IntegerField(
@ -1048,7 +1060,7 @@ class ConsolePortTemplateForm(BootstrapMixin, forms.ModelForm):
class ConsolePortTemplateCreateForm(BootstrapMixin, forms.Form):
device_type = forms.ModelChoiceField(
device_type = DynamicModelChoiceField(
queryset=DeviceType.objects.all(),
widget=APISelect(
api_url='/api/dcim/device-types/'
@ -1091,7 +1103,7 @@ class ConsoleServerPortTemplateForm(BootstrapMixin, forms.ModelForm):
class ConsoleServerPortTemplateCreateForm(BootstrapMixin, forms.Form):
device_type = forms.ModelChoiceField(
device_type = DynamicModelChoiceField(
queryset=DeviceType.objects.all(),
widget=APISelect(
api_url='/api/dcim/device-types/'
@ -1134,7 +1146,7 @@ class PowerPortTemplateForm(BootstrapMixin, forms.ModelForm):
class PowerPortTemplateCreateForm(BootstrapMixin, forms.Form):
device_type = forms.ModelChoiceField(
device_type = DynamicModelChoiceField(
queryset=DeviceType.objects.all(),
widget=APISelect(
api_url='/api/dcim/device-types/'
@ -1207,7 +1219,7 @@ class PowerOutletTemplateForm(BootstrapMixin, forms.ModelForm):
class PowerOutletTemplateCreateForm(BootstrapMixin, forms.Form):
device_type = forms.ModelChoiceField(
device_type = DynamicModelChoiceField(
queryset=DeviceType.objects.all(),
widget=APISelect(
api_url='/api/dcim/device-types/'
@ -1276,7 +1288,7 @@ class InterfaceTemplateForm(BootstrapMixin, forms.ModelForm):
class InterfaceTemplateCreateForm(BootstrapMixin, forms.Form):
device_type = forms.ModelChoiceField(
device_type = DynamicModelChoiceField(
queryset=DeviceType.objects.all(),
widget=APISelect(
api_url='/api/dcim/device-types/'
@ -1339,7 +1351,7 @@ class FrontPortTemplateForm(BootstrapMixin, forms.ModelForm):
class FrontPortTemplateCreateForm(BootstrapMixin, forms.Form):
device_type = forms.ModelChoiceField(
device_type = DynamicModelChoiceField(
queryset=DeviceType.objects.all(),
widget=APISelect(
api_url='/api/dcim/device-types/'
@ -1433,7 +1445,7 @@ class RearPortTemplateForm(BootstrapMixin, forms.ModelForm):
class RearPortTemplateCreateForm(BootstrapMixin, forms.Form):
device_type = forms.ModelChoiceField(
device_type = DynamicModelChoiceField(
queryset=DeviceType.objects.all(),
widget=APISelect(
api_url='/api/dcim/device-types/'
@ -1482,7 +1494,7 @@ class DeviceBayTemplateForm(BootstrapMixin, forms.ModelForm):
class DeviceBayTemplateCreateForm(BootstrapMixin, forms.Form):
device_type = forms.ModelChoiceField(
device_type = DynamicModelChoiceField(
queryset=DeviceType.objects.all(),
widget=APISelect(
api_url='/api/dcim/device-types/'
@ -1653,6 +1665,13 @@ class DeviceRoleCSVForm(forms.ModelForm):
#
class PlatformForm(BootstrapMixin, forms.ModelForm):
manufacturer = DynamicModelChoiceField(
queryset=Manufacturer.objects.all(),
required=False,
widget=APISelect(
api_url="/api/dcim/manufacturers/",
)
)
slug = SlugField(
max_length=64
)
@ -1663,9 +1682,6 @@ class PlatformForm(BootstrapMixin, forms.ModelForm):
'name', 'slug', 'manufacturer', 'napalm_driver', 'napalm_args',
]
widgets = {
'manufacturer': APISelect(
api_url="/api/dcim/manufacturers/"
),
'napalm_args': SmallTextarea(),
}
@ -1695,7 +1711,7 @@ class PlatformCSVForm(forms.ModelForm):
#
class DeviceForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
site = forms.ModelChoiceField(
site = DynamicModelChoiceField(
queryset=Site.objects.all(),
widget=APISelect(
api_url="/api/dcim/sites/",
@ -1721,7 +1737,7 @@ class DeviceForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
disabled_indicator='device'
)
)
manufacturer = forms.ModelChoiceField(
manufacturer = DynamicModelChoiceField(
queryset=Manufacturer.objects.all(),
required=False,
widget=APISelect(
@ -1734,13 +1750,28 @@ class DeviceForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
)
device_type = DynamicModelChoiceField(
queryset=DeviceType.objects.all(),
label='Device type',
widget=APISelect(
api_url='/api/dcim/device-types/',
display_field='model'
)
)
cluster_group = forms.ModelChoiceField(
device_role = DynamicModelChoiceField(
queryset=DeviceRole.objects.all(),
widget=APISelect(
api_url='/api/dcim/device-roles/'
)
)
platform = DynamicModelChoiceField(
queryset=Platform.objects.all(),
required=False,
widget=APISelect(
api_url="/api/dcim/platforms/",
additional_query_params={
"manufacturer_id": "null"
}
)
)
cluster_group = DynamicModelChoiceField(
queryset=ClusterGroup.objects.all(),
required=False,
widget=APISelect(
@ -1786,16 +1817,7 @@ class DeviceForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
'position': 'face'
}
),
'device_role': APISelect(
api_url='/api/dcim/device-roles/'
),
'status': StaticSelect2(),
'platform': APISelect(
api_url="/api/dcim/platforms/",
additional_query_params={
"manufacturer_id": "null"
}
),
'primary_ip4': StaticSelect2(),
'primary_ip6': StaticSelect2(),
}
@ -2069,31 +2091,29 @@ class DeviceBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditF
queryset=Device.objects.all(),
widget=forms.MultipleHiddenInput()
)
device_type = forms.ModelChoiceField(
device_type = DynamicModelChoiceField(
queryset=DeviceType.objects.all(),
required=False,
label='Type',
widget=APISelect(
api_url="/api/dcim/device-types/",
display_field='display_name'
)
)
device_role = forms.ModelChoiceField(
device_role = DynamicModelChoiceField(
queryset=DeviceRole.objects.all(),
required=False,
label='Role',
widget=APISelect(
api_url="/api/dcim/device-roles/"
)
)
tenant = forms.ModelChoiceField(
tenant = DynamicModelChoiceField(
queryset=Tenant.objects.all(),
required=False,
widget=APISelect(
api_url="/api/tenancy/tenants/"
)
)
platform = forms.ModelChoiceField(
platform = DynamicModelChoiceField(
queryset=Platform.objects.all(),
required=False,
widget=APISelect(
@ -2103,7 +2123,6 @@ class DeviceBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditF
status = forms.ChoiceField(
choices=add_blank_choice(DeviceStatusChoices),
required=False,
initial='',
widget=StaticSelect2()
)
serial = forms.CharField(
@ -2345,7 +2364,7 @@ class ConsolePortForm(BootstrapMixin, forms.ModelForm):
class ConsolePortCreateForm(BootstrapMixin, forms.Form):
device = forms.ModelChoiceField(
device = DynamicModelChoiceField(
queryset=Device.objects.prefetch_related('device_type__manufacturer'),
widget=APISelect(
api_url="/api/dcim/devices/",
@ -2430,7 +2449,7 @@ class ConsoleServerPortForm(BootstrapMixin, forms.ModelForm):
class ConsoleServerPortCreateForm(BootstrapMixin, forms.Form):
device = forms.ModelChoiceField(
device = DynamicModelChoiceField(
queryset=Device.objects.prefetch_related('device_type__manufacturer'),
widget=APISelect(
api_url="/api/dcim/devices/",
@ -2529,7 +2548,7 @@ class PowerPortForm(BootstrapMixin, forms.ModelForm):
class PowerPortCreateForm(BootstrapMixin, forms.Form):
device = forms.ModelChoiceField(
device = DynamicModelChoiceField(
queryset=Device.objects.prefetch_related('device_type__manufacturer'),
widget=APISelect(
api_url="/api/dcim/devices/",
@ -2647,7 +2666,7 @@ class PowerOutletForm(BootstrapMixin, forms.ModelForm):
class PowerOutletCreateForm(BootstrapMixin, forms.Form):
device = forms.ModelChoiceField(
device = DynamicModelChoiceField(
queryset=Device.objects.prefetch_related('device_type__manufacturer'),
widget=APISelect(
api_url="/api/dcim/devices/",
@ -2806,25 +2825,26 @@ class InterfaceFilterForm(DeviceComponentFilterForm):
class InterfaceForm(InterfaceCommonForm, BootstrapMixin, forms.ModelForm):
untagged_vlan = forms.ModelChoiceField(
untagged_vlan = DynamicModelChoiceField(
queryset=VLAN.objects.all(),
required=False,
label='Untagged VLAN',
widget=APISelect(
api_url="/api/ipam/vlans/",
display_field='display_name',
full=True
)
)
tagged_vlans = forms.ModelMultipleChoiceField(
tagged_vlans = DynamicModelMultipleChoiceField(
queryset=VLAN.objects.all(),
required=False,
label='Tagged VLANs',
widget=APISelectMultiple(
api_url="/api/ipam/vlans/",
display_field='display_name',
full=True
)
)
tags = TagField(
required=False
)
@ -2866,7 +2886,7 @@ class InterfaceForm(InterfaceCommonForm, BootstrapMixin, forms.ModelForm):
class InterfaceCreateForm(BootstrapMixin, InterfaceCommonForm, forms.Form):
device = forms.ModelChoiceField(
device = DynamicModelChoiceField(
queryset=Device.objects.prefetch_related('device_type__manufacturer'),
widget=APISelect(
api_url="/api/dcim/devices/",
@ -2916,7 +2936,7 @@ class InterfaceCreateForm(BootstrapMixin, InterfaceCommonForm, forms.Form):
tags = TagField(
required=False
)
untagged_vlan = forms.ModelChoiceField(
untagged_vlan = DynamicModelChoiceField(
queryset=VLAN.objects.all(),
required=False,
widget=APISelect(
@ -2925,7 +2945,7 @@ class InterfaceCreateForm(BootstrapMixin, InterfaceCommonForm, forms.Form):
full=True
)
)
tagged_vlans = forms.ModelMultipleChoiceField(
tagged_vlans = DynamicModelMultipleChoiceField(
queryset=VLAN.objects.all(),
required=False,
widget=APISelectMultiple(
@ -3064,7 +3084,7 @@ class InterfaceBulkEditForm(BootstrapMixin, AddRemoveTagsForm, BulkEditForm):
required=False,
widget=StaticSelect2()
)
untagged_vlan = forms.ModelChoiceField(
untagged_vlan = DynamicModelChoiceField(
queryset=VLAN.objects.all(),
required=False,
widget=APISelect(
@ -3073,7 +3093,7 @@ class InterfaceBulkEditForm(BootstrapMixin, AddRemoveTagsForm, BulkEditForm):
full=True
)
)
tagged_vlans = forms.ModelMultipleChoiceField(
tagged_vlans = DynamicModelMultipleChoiceField(
queryset=VLAN.objects.all(),
required=False,
widget=APISelectMultiple(
@ -3166,7 +3186,7 @@ class FrontPortForm(BootstrapMixin, forms.ModelForm):
# TODO: Merge with FrontPortTemplateCreateForm to remove duplicate logic
class FrontPortCreateForm(BootstrapMixin, forms.Form):
device = forms.ModelChoiceField(
device = DynamicModelChoiceField(
queryset=Device.objects.prefetch_related('device_type__manufacturer'),
widget=APISelect(
api_url="/api/dcim/devices/",
@ -3344,7 +3364,7 @@ class RearPortForm(BootstrapMixin, forms.ModelForm):
class RearPortCreateForm(BootstrapMixin, forms.Form):
device = forms.ModelChoiceField(
device = DynamicModelChoiceField(
queryset=Device.objects.prefetch_related('device_type__manufacturer'),
widget=APISelect(
api_url="/api/dcim/devices/",
@ -3429,7 +3449,7 @@ class ConnectCableToDeviceForm(BootstrapMixin, forms.ModelForm):
"""
Base form for connecting a Cable to a Device component
"""
termination_b_site = forms.ModelChoiceField(
termination_b_site = DynamicModelChoiceField(
queryset=Site.objects.all(),
label='Site',
required=False,
@ -3555,7 +3575,7 @@ class ConnectCableToRearPortForm(ConnectCableToDeviceForm):
class ConnectCableToCircuitTerminationForm(BootstrapMixin, forms.ModelForm):
termination_b_provider = forms.ModelChoiceField(
termination_b_provider = DynamicModelChoiceField(
queryset=Provider.objects.all(),
label='Provider',
required=False,
@ -3606,7 +3626,7 @@ class ConnectCableToCircuitTerminationForm(BootstrapMixin, forms.ModelForm):
class ConnectCableToPowerFeedForm(BootstrapMixin, forms.ModelForm):
termination_b_site = forms.ModelChoiceField(
termination_b_site = DynamicModelChoiceField(
queryset=Site.objects.all(),
label='Site',
required=False,
@ -3943,7 +3963,7 @@ class DeviceBayForm(BootstrapMixin, forms.ModelForm):
class DeviceBayCreateForm(BootstrapMixin, forms.Form):
device = forms.ModelChoiceField(
device = DynamicModelChoiceField(
queryset=Device.objects.prefetch_related('device_type__manufacturer'),
widget=APISelect(
api_url="/api/dcim/devices/",
@ -4113,6 +4133,19 @@ class InterfaceConnectionFilterForm(BootstrapMixin, forms.Form):
#
class InventoryItemForm(BootstrapMixin, forms.ModelForm):
device = DynamicModelChoiceField(
queryset=Device.objects.prefetch_related('device_type__manufacturer'),
widget=APISelect(
api_url="/api/dcim/devices/"
)
)
manufacturer = DynamicModelChoiceField(
queryset=Manufacturer.objects.all(),
required=False,
widget=APISelect(
api_url="/api/dcim/manufacturers/"
)
)
tags = TagField(
required=False
)
@ -4122,18 +4155,10 @@ class InventoryItemForm(BootstrapMixin, forms.ModelForm):
fields = [
'name', 'device', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description', 'tags',
]
widgets = {
'device': APISelect(
api_url="/api/dcim/devices/"
),
'manufacturer': APISelect(
api_url="/api/dcim/manufacturers/"
)
}
class InventoryItemCreateForm(BootstrapMixin, forms.Form):
device = forms.ModelChoiceField(
device = DynamicModelChoiceField(
queryset=Device.objects.prefetch_related('device_type__manufacturer'),
widget=APISelect(
api_url="/api/dcim/devices/",
@ -4142,7 +4167,7 @@ class InventoryItemCreateForm(BootstrapMixin, forms.Form):
name_pattern = ExpandableNameField(
label='Name'
)
manufacturer = forms.ModelChoiceField(
manufacturer = DynamicModelChoiceField(
queryset=Manufacturer.objects.all(),
required=False,
widget=APISelect(
@ -4197,14 +4222,14 @@ class InventoryItemBulkEditForm(BootstrapMixin, BulkEditForm):
queryset=InventoryItem.objects.all(),
widget=forms.MultipleHiddenInput()
)
device = forms.ModelChoiceField(
device = DynamicModelChoiceField(
queryset=Device.objects.all(),
required=False,
widget=APISelect(
api_url="/api/dcim/devices/"
)
)
manufacturer = forms.ModelChoiceField(
manufacturer = DynamicModelChoiceField(
queryset=Manufacturer.objects.all(),
required=False,
widget=APISelect(
@ -4364,7 +4389,7 @@ class DeviceVCMembershipForm(forms.ModelForm):
class VCMemberSelectForm(BootstrapMixin, forms.Form):
site = forms.ModelChoiceField(
site = DynamicModelChoiceField(
queryset=Site.objects.all(),
required=False,
widget=APISelect(
@ -4466,6 +4491,16 @@ class VirtualChassisFilterForm(BootstrapMixin, CustomFieldFilterForm):
#
class PowerPanelForm(BootstrapMixin, forms.ModelForm):
site = DynamicModelChoiceField(
queryset=Site.objects.all(),
required=False,
widget=APISelect(
api_url="/api/dcim/sites/",
filter_for={
'rack_group': 'site_id',
}
)
)
rack_group = DynamicModelChoiceField(
queryset=RackGroup.objects.all(),
required=False,
@ -4479,14 +4514,6 @@ class PowerPanelForm(BootstrapMixin, forms.ModelForm):
fields = [
'site', 'rack_group', 'name',
]
widgets = {
'site': APISelect(
api_url="/api/dcim/sites/",
filter_for={
'rack_group': 'site_id',
}
),
}
class PowerPanelCSVForm(forms.ModelForm):
@ -4581,6 +4608,19 @@ class PowerFeedForm(BootstrapMixin, CustomFieldModelForm):
}
)
)
power_panel = DynamicModelChoiceField(
queryset=PowerPanel.objects.all(),
widget=APISelect(
api_url="/api/dcim/power-panels/"
)
)
rack = DynamicModelChoiceField(
queryset=Rack.objects.all(),
required=False,
widget=APISelect(
api_url="/api/dcim/racks/"
)
)
comments = CommentField()
tags = TagField(
required=False
@ -4593,12 +4633,6 @@ class PowerFeedForm(BootstrapMixin, CustomFieldModelForm):
'max_utilization', 'comments', 'tags',
]
widgets = {
'power_panel': APISelect(
api_url="/api/dcim/power-panels/"
),
'rack': APISelect(
api_url="/api/dcim/racks/"
),
'status': StaticSelect2(),
'type': StaticSelect2(),
'supply': StaticSelect2(),
@ -4697,7 +4731,7 @@ class PowerFeedBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEd
queryset=PowerFeed.objects.all(),
widget=forms.MultipleHiddenInput
)
power_panel = forms.ModelChoiceField(
power_panel = DynamicModelChoiceField(
queryset=PowerPanel.objects.all(),
required=False,
widget=APISelect(
@ -4707,7 +4741,7 @@ class PowerFeedBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEd
}
)
)
rack = forms.ModelChoiceField(
rack = DynamicModelChoiceField(
queryset=Rack.objects.all(),
required=False,
widget=APISelect(

View File

@ -196,7 +196,56 @@ class ConfigContextForm(BootstrapMixin, forms.ModelForm):
required=False,
widget=StaticSelect2Multiple()
)
tags = forms.ModelMultipleChoiceField(
sites = DynamicModelMultipleChoiceField(
queryset=Site.objects.all(),
required=False,
widget=APISelectMultiple(
api_url="/api/dcim/sites/"
)
)
roles = DynamicModelMultipleChoiceField(
queryset=DeviceRole.objects.all(),
required=False,
widget=APISelectMultiple(
api_url="/api/dcim/device-roles/"
)
)
platforms = DynamicModelMultipleChoiceField(
queryset=Platform.objects.all(),
required=False,
widget=APISelectMultiple(
api_url="/api/dcim/platforms/"
)
)
cluster_groups = DynamicModelMultipleChoiceField(
queryset=ClusterGroup.objects.all(),
required=False,
widget=APISelectMultiple(
api_url="/api/virtualization/cluster-groups/"
)
)
clusters = DynamicModelMultipleChoiceField(
queryset=Cluster.objects.all(),
required=False,
widget=APISelectMultiple(
api_url="/api/virtualization/clusters/"
)
)
tenant_groups = DynamicModelMultipleChoiceField(
queryset=TenantGroup.objects.all(),
required=False,
widget=APISelectMultiple(
api_url="/api/tenancy/tenant-groups/"
)
)
tenants = DynamicModelMultipleChoiceField(
queryset=Tenant.objects.all(),
required=False,
widget=APISelectMultiple(
api_url="/api/tenancy/tenants/"
)
)
tags = DynamicModelMultipleChoiceField(
queryset=Tag.objects.all(),
to_field_name='slug',
required=False,
@ -210,36 +259,10 @@ class ConfigContextForm(BootstrapMixin, forms.ModelForm):
class Meta:
model = ConfigContext
fields = [
fields = (
'name', 'weight', 'description', 'is_active', 'regions', 'sites', 'roles', 'platforms', 'cluster_groups',
'clusters', 'tenant_groups', 'tenants', 'tags', 'data',
]
widgets = {
'regions': APISelectMultiple(
api_url="/api/dcim/regions/"
),
'sites': APISelectMultiple(
api_url="/api/dcim/sites/"
),
'roles': APISelectMultiple(
api_url="/api/dcim/device-roles/"
),
'platforms': APISelectMultiple(
api_url="/api/dcim/platforms/"
),
'cluster_groups': APISelectMultiple(
api_url="/api/virtualization/cluster-groups/"
),
'clusters': APISelectMultiple(
api_url="/api/virtualization/clusters/"
),
'tenant_groups': APISelectMultiple(
api_url="/api/tenancy/tenant-groups/"
),
'tenants': APISelectMultiple(
api_url="/api/tenancy/tenants/"
),
}
)
class ConfigContextBulkEditForm(BootstrapMixin, BulkEditForm):

View File

@ -76,7 +76,7 @@ class VRFBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm
queryset=VRF.objects.all(),
widget=forms.MultipleHiddenInput()
)
tenant = forms.ModelChoiceField(
tenant = DynamicModelChoiceField(
queryset=Tenant.objects.all(),
required=False,
widget=APISelect(
@ -149,6 +149,12 @@ class RIRFilterForm(BootstrapMixin, forms.Form):
#
class AggregateForm(BootstrapMixin, CustomFieldModelForm):
rir = DynamicModelChoiceField(
queryset=RIR.objects.all(),
widget=APISelect(
api_url="/api/ipam/rirs/"
)
)
tags = TagField(
required=False
)
@ -163,9 +169,6 @@ class AggregateForm(BootstrapMixin, CustomFieldModelForm):
'rir': "Regional Internet Registry responsible for this prefix",
}
widgets = {
'rir': APISelect(
api_url="/api/ipam/rirs/"
),
'date_added': DatePicker(),
}
@ -190,7 +193,7 @@ class AggregateBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEd
queryset=Aggregate.objects.all(),
widget=forms.MultipleHiddenInput()
)
rir = forms.ModelChoiceField(
rir = DynamicModelChoiceField(
queryset=RIR.objects.all(),
required=False,
label='RIR',
@ -270,7 +273,14 @@ class RoleCSVForm(forms.ModelForm):
#
class PrefixForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
site = forms.ModelChoiceField(
vrf = DynamicModelChoiceField(
queryset=VRF.objects.all(),
required=False,
widget=APISelect(
api_url="/api/ipam/vrfs/",
)
)
site = DynamicModelChoiceField(
queryset=Site.objects.all(),
required=False,
widget=APISelect(
@ -307,6 +317,13 @@ class PrefixForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
display_field='display_name'
)
)
role = DynamicModelChoiceField(
queryset=Role.objects.all(),
required=False,
widget=APISelect(
api_url="/api/ipam/roles/"
)
)
tags = TagField(required=False)
class Meta:
@ -316,13 +333,7 @@ class PrefixForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
'tags',
]
widgets = {
'vrf': APISelect(
api_url="/api/ipam/vrfs/"
),
'status': StaticSelect2(),
'role': APISelect(
api_url="/api/ipam/roles/"
)
}
def __init__(self, *args, **kwargs):
@ -433,14 +444,14 @@ class PrefixBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditF
queryset=Prefix.objects.all(),
widget=forms.MultipleHiddenInput()
)
site = forms.ModelChoiceField(
site = DynamicModelChoiceField(
queryset=Site.objects.all(),
required=False,
widget=APISelect(
api_url="/api/dcim/sites/"
)
)
vrf = forms.ModelChoiceField(
vrf = DynamicModelChoiceField(
queryset=VRF.objects.all(),
required=False,
label='VRF',
@ -453,7 +464,7 @@ class PrefixBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditF
max_value=PREFIX_LENGTH_MAX,
required=False
)
tenant = forms.ModelChoiceField(
tenant = DynamicModelChoiceField(
queryset=Tenant.objects.all(),
required=False,
widget=APISelect(
@ -465,7 +476,7 @@ class PrefixBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditF
required=False,
widget=StaticSelect2()
)
role = forms.ModelChoiceField(
role = DynamicModelChoiceField(
queryset=Role.objects.all(),
required=False,
widget=APISelect(
@ -588,7 +599,15 @@ class IPAddressForm(BootstrapMixin, TenancyForm, ReturnURLForm, CustomFieldModel
queryset=Interface.objects.all(),
required=False
)
nat_site = forms.ModelChoiceField(
vrf = DynamicModelChoiceField(
queryset=VRF.objects.all(),
required=False,
label='VRF',
widget=APISelect(
api_url="/api/ipam/vrfs/"
)
)
nat_site = DynamicModelChoiceField(
queryset=Site.objects.all(),
required=False,
label='Site',
@ -664,9 +683,6 @@ class IPAddressForm(BootstrapMixin, TenancyForm, ReturnURLForm, CustomFieldModel
widgets = {
'status': StaticSelect2(),
'role': StaticSelect2(),
'vrf': APISelect(
api_url="/api/ipam/vrfs/"
)
}
def __init__(self, *args, **kwargs):
@ -741,6 +757,14 @@ class IPAddressBulkCreateForm(BootstrapMixin, forms.Form):
class IPAddressBulkAddForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
vrf = DynamicModelChoiceField(
queryset=VRF.objects.all(),
required=False,
label='VRF',
widget=APISelect(
api_url="/api/ipam/vrfs/"
)
)
class Meta:
model = IPAddress
@ -750,9 +774,6 @@ class IPAddressBulkAddForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
widgets = {
'status': StaticSelect2(),
'role': StaticSelect2(),
'vrf': APISelect(
api_url="/api/ipam/vrfs/"
)
}
def __init__(self, *args, **kwargs):
@ -888,7 +909,7 @@ class IPAddressBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEd
queryset=IPAddress.objects.all(),
widget=forms.MultipleHiddenInput()
)
vrf = forms.ModelChoiceField(
vrf = DynamicModelChoiceField(
queryset=VRF.objects.all(),
required=False,
label='VRF',
@ -901,7 +922,7 @@ class IPAddressBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEd
max_value=IPADDRESS_MASK_LENGTH_MAX,
required=False
)
tenant = forms.ModelChoiceField(
tenant = DynamicModelChoiceField(
queryset=Tenant.objects.all(),
required=False,
widget=APISelect(
@ -934,7 +955,7 @@ class IPAddressBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEd
class IPAddressAssignForm(BootstrapMixin, forms.Form):
vrf_id = forms.ModelChoiceField(
vrf_id = DynamicModelChoiceField(
queryset=VRF.objects.all(),
required=False,
label='VRF',
@ -1014,6 +1035,13 @@ class IPAddressFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterFo
#
class VLANGroupForm(BootstrapMixin, forms.ModelForm):
site = DynamicModelChoiceField(
queryset=Site.objects.all(),
required=False,
widget=APISelect(
api_url="/api/dcim/sites/"
)
)
slug = SlugField()
class Meta:
@ -1021,11 +1049,6 @@ class VLANGroupForm(BootstrapMixin, forms.ModelForm):
fields = [
'site', 'name', 'slug',
]
widgets = {
'site': APISelect(
api_url="/api/dcim/sites/"
)
}
class VLANGroupCSVForm(forms.ModelForm):
@ -1078,7 +1101,7 @@ class VLANGroupFilterForm(BootstrapMixin, forms.Form):
#
class VLANForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
site = forms.ModelChoiceField(
site = DynamicModelChoiceField(
queryset=Site.objects.all(),
required=False,
widget=APISelect(
@ -1098,6 +1121,13 @@ class VLANForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
api_url='/api/ipam/vlan-groups/',
)
)
role = DynamicModelChoiceField(
queryset=Role.objects.all(),
required=False,
widget=APISelect(
api_url="/api/ipam/roles/"
)
)
tags = TagField(required=False)
class Meta:
@ -1115,9 +1145,6 @@ class VLANForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
}
widgets = {
'status': StaticSelect2(),
'role': APISelect(
api_url="/api/ipam/roles/"
)
}
@ -1192,21 +1219,21 @@ class VLANBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditFor
queryset=VLAN.objects.all(),
widget=forms.MultipleHiddenInput()
)
site = forms.ModelChoiceField(
site = DynamicModelChoiceField(
queryset=Site.objects.all(),
required=False,
widget=APISelect(
api_url="/api/dcim/sites/"
)
)
group = forms.ModelChoiceField(
group = DynamicModelChoiceField(
queryset=VLANGroup.objects.all(),
required=False,
widget=APISelect(
api_url="/api/ipam/vlan-groups/"
)
)
tenant = forms.ModelChoiceField(
tenant = DynamicModelChoiceField(
queryset=Tenant.objects.all(),
required=False,
widget=APISelect(
@ -1218,7 +1245,7 @@ class VLANBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditFor
required=False,
widget=StaticSelect2()
)
role = forms.ModelChoiceField(
role = DynamicModelChoiceField(
queryset=Role.objects.all(),
required=False,
widget=APISelect(

View File

@ -8,8 +8,8 @@ from extras.forms import (
AddRemoveTagsForm, CustomFieldBulkEditForm, CustomFieldFilterForm, CustomFieldModelForm, CustomFieldModelCSVForm,
)
from utilities.forms import (
APISelect, APISelectMultiple, BootstrapMixin, DynamicModelMultipleChoiceField, FlexibleModelChoiceField, SlugField,
StaticSelect2Multiple, TagFilterField
APISelect, APISelectMultiple, BootstrapMixin, DynamicModelChoiceField, DynamicModelMultipleChoiceField,
FlexibleModelChoiceField, SlugField, StaticSelect2Multiple, TagFilterField,
)
from .constants import *
from .models import Secret, SecretRole, UserKey
@ -87,6 +87,12 @@ class SecretForm(BootstrapMixin, CustomFieldModelForm):
label='Plaintext (verify)',
widget=forms.PasswordInput()
)
role = DynamicModelChoiceField(
queryset=SecretRole.objects.all(),
widget=APISelect(
api_url="/api/secrets/secret-roles/"
)
)
tags = TagField(
required=False
)
@ -96,11 +102,6 @@ class SecretForm(BootstrapMixin, CustomFieldModelForm):
fields = [
'role', 'name', 'plaintext', 'plaintext2', 'tags',
]
widgets = {
'role': APISelect(
api_url="/api/secrets/secret-roles/"
)
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@ -157,7 +158,7 @@ class SecretBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditF
queryset=Secret.objects.all(),
widget=forms.MultipleHiddenInput()
)
role = forms.ModelChoiceField(
role = DynamicModelChoiceField(
queryset=SecretRole.objects.all(),
required=False,
widget=APISelect(

View File

@ -42,6 +42,13 @@ class TenantGroupCSVForm(forms.ModelForm):
class TenantForm(BootstrapMixin, CustomFieldModelForm):
slug = SlugField()
group = DynamicModelChoiceField(
queryset=TenantGroup.objects.all(),
required=False,
widget=APISelect(
api_url="/api/tenancy/tenant-groups/"
)
)
comments = CommentField()
tags = TagField(
required=False
@ -49,14 +56,9 @@ class TenantForm(BootstrapMixin, CustomFieldModelForm):
class Meta:
model = Tenant
fields = [
fields = (
'name', 'slug', 'group', 'description', 'comments', 'tags',
]
widgets = {
'group': APISelect(
api_url="/api/tenancy/tenant-groups/"
)
}
class TenantCSVForm(CustomFieldModelForm):
@ -85,7 +87,7 @@ class TenantBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditF
queryset=Tenant.objects.all(),
widget=forms.MultipleHiddenInput()
)
group = forms.ModelChoiceField(
group = DynamicModelChoiceField(
queryset=TenantGroup.objects.all(),
required=False,
widget=APISelect(

View File

@ -550,11 +550,7 @@ class TagFilterField(forms.MultipleChoiceField):
super().__init__(label='Tags', choices=get_choices, required=False, *args, **kwargs)
class DynamicModelChoiceField(forms.ModelChoiceField):
"""
Override get_bound_field() to avoid pre-populating field choices with a SQL query. The field will be
rendered only with choices set via bound data. Choices are populated on-demand via the APISelect widget.
"""
class DynamicModelChoiceMixin:
field_modifier = ''
def get_bound_field(self, form, field_name):
@ -564,16 +560,24 @@ class DynamicModelChoiceField(forms.ModelChoiceField):
# will be populated on-demand via the APISelect widget.
field_name = '{}{}'.format(self.to_field_name or 'pk', self.field_modifier)
if bound_field.data:
self.queryset = self.queryset.filter(**{field_name: bound_field.data})
self.queryset = self.queryset.filter(**{field_name: self.prepare_value(bound_field.data)})
elif bound_field.initial:
self.queryset = self.queryset.filter(**{field_name: bound_field.initial})
self.queryset = self.queryset.filter(**{field_name: self.prepare_value(bound_field.initial)})
else:
self.queryset = self.queryset.none()
return bound_field
class DynamicModelMultipleChoiceField(DynamicModelChoiceField):
class DynamicModelChoiceField(DynamicModelChoiceMixin, forms.ModelChoiceField):
"""
Override get_bound_field() to avoid pre-populating field choices with a SQL query. The field will be
rendered only with choices set via bound data. Choices are populated on-demand via the APISelect widget.
"""
pass
class DynamicModelMultipleChoiceField(DynamicModelChoiceMixin, forms.ModelMultipleChoiceField):
"""
A multiple-choice version of DynamicModelChoiceField.
"""

View File

@ -76,6 +76,26 @@ class ClusterGroupCSVForm(forms.ModelForm):
#
class ClusterForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
type = DynamicModelChoiceField(
queryset=ClusterType.objects.all(),
widget=APISelect(
api_url="/api/virtualization/cluster-types/"
)
)
group = DynamicModelChoiceField(
queryset=ClusterGroup.objects.all(),
required=False,
widget=APISelect(
api_url="/api/virtualization/cluster-groups/"
)
)
site = DynamicModelChoiceField(
queryset=Site.objects.all(),
required=False,
widget=APISelect(
api_url="/api/dcim/sites/"
)
)
comments = CommentField()
tags = TagField(
required=False
@ -83,20 +103,9 @@ class ClusterForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
class Meta:
model = Cluster
fields = [
fields = (
'name', 'type', 'group', 'tenant', 'site', 'comments', 'tags',
]
widgets = {
'type': APISelect(
api_url="/api/virtualization/cluster-types/"
),
'group': APISelect(
api_url="/api/virtualization/cluster-groups/"
),
'site': APISelect(
api_url="/api/dcim/sites/"
),
}
)
class ClusterCSVForm(CustomFieldModelCSVForm):
@ -146,25 +155,28 @@ class ClusterBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEdit
queryset=Cluster.objects.all(),
widget=forms.MultipleHiddenInput()
)
type = forms.ModelChoiceField(
type = DynamicModelChoiceField(
queryset=ClusterType.objects.all(),
required=False,
widget=APISelect(
api_url="/api/virtualization/cluster-types/"
)
)
group = forms.ModelChoiceField(
group = DynamicModelChoiceField(
queryset=ClusterGroup.objects.all(),
required=False,
widget=APISelect(
api_url="/api/virtualization/cluster-groups/"
)
)
tenant = forms.ModelChoiceField(
tenant = DynamicModelChoiceField(
queryset=Tenant.objects.all(),
required=False
required=False,
widget=APISelect(
api_url="/api/tenancy/tenants/"
)
site = forms.ModelChoiceField(
)
site = DynamicModelChoiceField(
queryset=Site.objects.all(),
required=False,
widget=APISelect(
@ -233,7 +245,7 @@ class ClusterFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm
class ClusterAddDevicesForm(BootstrapMixin, forms.Form):
region = forms.ModelChoiceField(
region = DynamicModelChoiceField(
queryset=Region.objects.all(),
required=False,
widget=APISelect(
@ -318,7 +330,7 @@ class ClusterRemoveDevicesForm(ConfirmationForm):
#
class VirtualMachineForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
cluster_group = forms.ModelChoiceField(
cluster_group = DynamicModelChoiceField(
queryset=ClusterGroup.objects.all(),
required=False,
widget=APISelect(
@ -337,6 +349,22 @@ class VirtualMachineForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
api_url='/api/virtualization/clusters/'
)
)
role = DynamicModelChoiceField(
queryset=DeviceRole.objects.all(),
widget=APISelect(
api_url="/api/dcim/device-roles/",
additional_query_params={
"vm_role": "True"
}
)
)
platform = DynamicModelChoiceField(
queryset=Platform.objects.all(),
required=False,
widget=APISelect(
api_url='/api/dcim/platforms/'
)
)
tags = TagField(
required=False
)
@ -357,17 +385,8 @@ class VirtualMachineForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
}
widgets = {
"status": StaticSelect2(),
"role": APISelect(
api_url="/api/dcim/device-roles/",
additional_query_params={
"vm_role": "True"
}
),
'primary_ip4': StaticSelect2(),
'primary_ip6': StaticSelect2(),
'platform': APISelect(
api_url='/api/dcim/platforms/'
)
}
def __init__(self, *args, **kwargs):
@ -477,14 +496,14 @@ class VirtualMachineBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldB
initial='',
widget=StaticSelect2(),
)
cluster = forms.ModelChoiceField(
cluster = DynamicModelChoiceField(
queryset=Cluster.objects.all(),
required=False,
widget=APISelect(
api_url='/api/virtualization/clusters/'
)
)
role = forms.ModelChoiceField(
role = DynamicModelChoiceField(
queryset=DeviceRole.objects.filter(
vm_role=True
),
@ -496,14 +515,14 @@ class VirtualMachineBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldB
}
)
)
tenant = forms.ModelChoiceField(
tenant = DynamicModelChoiceField(
queryset=Tenant.objects.all(),
required=False,
widget=APISelect(
api_url='/api/tenancy/tenants/'
)
)
platform = forms.ModelChoiceField(
platform = DynamicModelChoiceField(
queryset=Platform.objects.all(),
required=False,
widget=APISelect(
@ -633,7 +652,7 @@ class VirtualMachineFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFil
#
class InterfaceForm(BootstrapMixin, forms.ModelForm):
untagged_vlan = forms.ModelChoiceField(
untagged_vlan = DynamicModelChoiceField(
queryset=VLAN.objects.all(),
required=False,
widget=APISelect(
@ -642,7 +661,7 @@ class InterfaceForm(BootstrapMixin, forms.ModelForm):
full=True
)
)
tagged_vlans = forms.ModelMultipleChoiceField(
tagged_vlans = DynamicModelMultipleChoiceField(
queryset=VLAN.objects.all(),
required=False,
widget=APISelectMultiple(
@ -759,7 +778,7 @@ class InterfaceCreateForm(BootstrapMixin, forms.Form):
required=False,
widget=StaticSelect2(),
)
untagged_vlan = forms.ModelChoiceField(
untagged_vlan = DynamicModelChoiceField(
queryset=VLAN.objects.all(),
required=False,
widget=APISelect(
@ -768,7 +787,7 @@ class InterfaceCreateForm(BootstrapMixin, forms.Form):
full=True
)
)
tagged_vlans = forms.ModelMultipleChoiceField(
tagged_vlans = DynamicModelMultipleChoiceField(
queryset=VLAN.objects.all(),
required=False,
widget=APISelectMultiple(
@ -847,7 +866,7 @@ class InterfaceBulkEditForm(BootstrapMixin, BulkEditForm):
required=False,
widget=StaticSelect2()
)
untagged_vlan = forms.ModelChoiceField(
untagged_vlan = DynamicModelChoiceField(
queryset=VLAN.objects.all(),
required=False,
widget=APISelect(
@ -856,7 +875,7 @@ class InterfaceBulkEditForm(BootstrapMixin, BulkEditForm):
full=True
)
)
tagged_vlans = forms.ModelMultipleChoiceField(
tagged_vlans = DynamicModelMultipleChoiceField(
queryset=VLAN.objects.all(),
required=False,
widget=APISelectMultiple(