Merge pull request #4375 from netbox-community/4374-dynamic-fields-api-url

Closes #4374: Automatically derive API endpoint for dynamic choice fields
This commit is contained in:
Jeremy Stretch 2020-03-16 16:02:25 -04:00 committed by GitHub
commit 00afe7aa94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 127 additions and 559 deletions

View File

@ -113,7 +113,6 @@ class ProviderFilterForm(BootstrapMixin, CustomFieldFilterForm):
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/regions/",
value_field="slug", value_field="slug",
filter_for={ filter_for={
'site': 'region' 'site': 'region'
@ -125,7 +124,6 @@ class ProviderFilterForm(BootstrapMixin, CustomFieldFilterForm):
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/sites/",
value_field="slug", value_field="slug",
) )
) )
@ -167,16 +165,10 @@ class CircuitTypeCSVForm(forms.ModelForm):
class CircuitForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): class CircuitForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
provider = DynamicModelChoiceField( provider = DynamicModelChoiceField(
queryset=Provider.objects.all(), queryset=Provider.objects.all()
widget=APISelect(
api_url="/api/circuits/providers/"
)
) )
type = DynamicModelChoiceField( type = DynamicModelChoiceField(
queryset=CircuitType.objects.all(), queryset=CircuitType.objects.all()
widget=APISelect(
api_url="/api/circuits/circuit-types/"
)
) )
comments = CommentField() comments = CommentField()
tags = TagField( tags = TagField(
@ -245,17 +237,11 @@ class CircuitBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEdit
) )
type = DynamicModelChoiceField( type = DynamicModelChoiceField(
queryset=CircuitType.objects.all(), queryset=CircuitType.objects.all(),
required=False, required=False
widget=APISelect(
api_url="/api/circuits/circuit-types/"
)
) )
provider = DynamicModelChoiceField( provider = DynamicModelChoiceField(
queryset=Provider.objects.all(), queryset=Provider.objects.all(),
required=False, required=False
widget=APISelect(
api_url="/api/circuits/providers/"
)
) )
status = forms.ChoiceField( status = forms.ChoiceField(
choices=add_blank_choice(CircuitStatusChoices), choices=add_blank_choice(CircuitStatusChoices),
@ -265,10 +251,7 @@ class CircuitBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEdit
) )
tenant = DynamicModelChoiceField( tenant = DynamicModelChoiceField(
queryset=Tenant.objects.all(), queryset=Tenant.objects.all(),
required=False, required=False
widget=APISelect(
api_url="/api/tenancy/tenants/"
)
) )
commit_rate = forms.IntegerField( commit_rate = forms.IntegerField(
required=False, required=False,
@ -303,7 +286,6 @@ class CircuitFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/circuits/circuit-types/",
value_field="slug", value_field="slug",
) )
) )
@ -312,7 +294,6 @@ class CircuitFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/circuits/providers/",
value_field="slug", value_field="slug",
) )
) )
@ -326,7 +307,6 @@ class CircuitFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/regions/",
value_field="slug", value_field="slug",
filter_for={ filter_for={
'site': 'region' 'site': 'region'
@ -338,7 +318,6 @@ class CircuitFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/sites/",
value_field="slug", value_field="slug",
) )
) )
@ -355,6 +334,9 @@ class CircuitFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm
# #
class CircuitTerminationForm(BootstrapMixin, forms.ModelForm): class CircuitTerminationForm(BootstrapMixin, forms.ModelForm):
site = DynamicModelChoiceField(
queryset=Site.objects.all()
)
class Meta: class Meta:
model = CircuitTermination model = CircuitTermination
@ -368,7 +350,4 @@ class CircuitTerminationForm(BootstrapMixin, forms.ModelForm):
} }
widgets = { widgets = {
'term_side': forms.HiddenInput(), 'term_side': forms.HiddenInput(),
'site': APISelect(
api_url="/api/dcim/sites/"
)
} }

File diff suppressed because it is too large Load Diff

View File

@ -198,60 +198,36 @@ class ConfigContextForm(BootstrapMixin, forms.ModelForm):
) )
sites = DynamicModelMultipleChoiceField( sites = DynamicModelMultipleChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
required=False, required=False
widget=APISelectMultiple(
api_url="/api/dcim/sites/"
)
) )
roles = DynamicModelMultipleChoiceField( roles = DynamicModelMultipleChoiceField(
queryset=DeviceRole.objects.all(), queryset=DeviceRole.objects.all(),
required=False, required=False
widget=APISelectMultiple(
api_url="/api/dcim/device-roles/"
)
) )
platforms = DynamicModelMultipleChoiceField( platforms = DynamicModelMultipleChoiceField(
queryset=Platform.objects.all(), queryset=Platform.objects.all(),
required=False, required=False
widget=APISelectMultiple(
api_url="/api/dcim/platforms/"
)
) )
cluster_groups = DynamicModelMultipleChoiceField( cluster_groups = DynamicModelMultipleChoiceField(
queryset=ClusterGroup.objects.all(), queryset=ClusterGroup.objects.all(),
required=False, required=False
widget=APISelectMultiple(
api_url="/api/virtualization/cluster-groups/"
)
) )
clusters = DynamicModelMultipleChoiceField( clusters = DynamicModelMultipleChoiceField(
queryset=Cluster.objects.all(), queryset=Cluster.objects.all(),
required=False, required=False
widget=APISelectMultiple(
api_url="/api/virtualization/clusters/"
)
) )
tenant_groups = DynamicModelMultipleChoiceField( tenant_groups = DynamicModelMultipleChoiceField(
queryset=TenantGroup.objects.all(), queryset=TenantGroup.objects.all(),
required=False, required=False
widget=APISelectMultiple(
api_url="/api/tenancy/tenant-groups/"
)
) )
tenants = DynamicModelMultipleChoiceField( tenants = DynamicModelMultipleChoiceField(
queryset=Tenant.objects.all(), queryset=Tenant.objects.all(),
required=False, required=False
widget=APISelectMultiple(
api_url="/api/tenancy/tenants/"
)
) )
tags = DynamicModelMultipleChoiceField( tags = DynamicModelMultipleChoiceField(
queryset=Tag.objects.all(), queryset=Tag.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False, required=False
widget=APISelectMultiple(
api_url="/api/extras/tags/"
)
) )
data = JSONField( data = JSONField(
label='' label=''
@ -299,7 +275,6 @@ class ConfigContextFilterForm(BootstrapMixin, forms.Form):
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/regions/",
value_field="slug", value_field="slug",
) )
) )
@ -308,7 +283,6 @@ class ConfigContextFilterForm(BootstrapMixin, forms.Form):
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/sites/",
value_field="slug", value_field="slug",
) )
) )
@ -317,7 +291,6 @@ class ConfigContextFilterForm(BootstrapMixin, forms.Form):
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/device-roles/",
value_field="slug", value_field="slug",
) )
) )
@ -326,7 +299,6 @@ class ConfigContextFilterForm(BootstrapMixin, forms.Form):
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/platforms/",
value_field="slug", value_field="slug",
) )
) )
@ -335,24 +307,19 @@ class ConfigContextFilterForm(BootstrapMixin, forms.Form):
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/virtualization/cluster-groups/",
value_field="slug", value_field="slug",
) )
) )
cluster_id = DynamicModelMultipleChoiceField( cluster_id = DynamicModelMultipleChoiceField(
queryset=Cluster.objects.all(), queryset=Cluster.objects.all(),
required=False, required=False,
label='Cluster', label='Cluster'
widget=APISelectMultiple(
api_url="/api/virtualization/clusters/",
)
) )
tenant_group = DynamicModelMultipleChoiceField( tenant_group = DynamicModelMultipleChoiceField(
queryset=TenantGroup.objects.all(), queryset=TenantGroup.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/tenancy/tenant-groups/",
value_field="slug", value_field="slug",
) )
) )
@ -361,7 +328,6 @@ class ConfigContextFilterForm(BootstrapMixin, forms.Form):
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/tenancy/tenants/",
value_field="slug", value_field="slug",
) )
) )
@ -370,7 +336,6 @@ class ConfigContextFilterForm(BootstrapMixin, forms.Form):
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/extras/tags/",
value_field="slug", value_field="slug",
) )
) )

View File

@ -78,10 +78,7 @@ class VRFBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm
) )
tenant = DynamicModelChoiceField( tenant = DynamicModelChoiceField(
queryset=Tenant.objects.all(), queryset=Tenant.objects.all(),
required=False, required=False
widget=APISelect(
api_url="/api/tenancy/tenants/"
)
) )
enforce_unique = forms.NullBooleanField( enforce_unique = forms.NullBooleanField(
required=False, required=False,
@ -150,10 +147,7 @@ class RIRFilterForm(BootstrapMixin, forms.Form):
class AggregateForm(BootstrapMixin, CustomFieldModelForm): class AggregateForm(BootstrapMixin, CustomFieldModelForm):
rir = DynamicModelChoiceField( rir = DynamicModelChoiceField(
queryset=RIR.objects.all(), queryset=RIR.objects.all()
widget=APISelect(
api_url="/api/ipam/rirs/"
)
) )
tags = TagField( tags = TagField(
required=False required=False
@ -196,10 +190,7 @@ class AggregateBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEd
rir = DynamicModelChoiceField( rir = DynamicModelChoiceField(
queryset=RIR.objects.all(), queryset=RIR.objects.all(),
required=False, required=False,
label='RIR', label='RIR'
widget=APISelect(
api_url="/api/ipam/rirs/"
)
) )
date_added = forms.DateField( date_added = forms.DateField(
required=False required=False
@ -236,7 +227,6 @@ class AggregateFilterForm(BootstrapMixin, CustomFieldFilterForm):
required=False, required=False,
label='RIR', label='RIR',
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/ipam/rirs/",
value_field="slug", value_field="slug",
) )
) )
@ -276,16 +266,12 @@ class PrefixForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
vrf = DynamicModelChoiceField( vrf = DynamicModelChoiceField(
queryset=VRF.objects.all(), queryset=VRF.objects.all(),
required=False, required=False,
label='VRF', label='VRF'
widget=APISelect(
api_url="/api/ipam/vrfs/",
)
) )
site = DynamicModelChoiceField( site = DynamicModelChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
required=False, required=False,
widget=APISelect( widget=APISelect(
api_url="/api/dcim/sites/",
filter_for={ filter_for={
'vlan_group': 'site_id', 'vlan_group': 'site_id',
'vlan': 'site_id', 'vlan': 'site_id',
@ -300,7 +286,6 @@ class PrefixForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
required=False, required=False,
label='VLAN group', label='VLAN group',
widget=APISelect( widget=APISelect(
api_url='/api/ipam/vlan-groups/',
filter_for={ filter_for={
'vlan': 'group_id' 'vlan': 'group_id'
}, },
@ -314,16 +299,12 @@ class PrefixForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
required=False, required=False,
label='VLAN', label='VLAN',
widget=APISelect( widget=APISelect(
api_url='/api/ipam/vlans/',
display_field='display_name' display_field='display_name'
) )
) )
role = DynamicModelChoiceField( role = DynamicModelChoiceField(
queryset=Role.objects.all(), queryset=Role.objects.all(),
required=False, required=False
widget=APISelect(
api_url="/api/ipam/roles/"
)
) )
tags = TagField(required=False) tags = TagField(required=False)
@ -447,18 +428,12 @@ class PrefixBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditF
) )
site = DynamicModelChoiceField( site = DynamicModelChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
required=False, required=False
widget=APISelect(
api_url="/api/dcim/sites/"
)
) )
vrf = DynamicModelChoiceField( vrf = DynamicModelChoiceField(
queryset=VRF.objects.all(), queryset=VRF.objects.all(),
required=False, required=False,
label='VRF', label='VRF'
widget=APISelect(
api_url="/api/ipam/vrfs/"
)
) )
prefix_length = forms.IntegerField( prefix_length = forms.IntegerField(
min_value=PREFIX_LENGTH_MIN, min_value=PREFIX_LENGTH_MIN,
@ -467,10 +442,7 @@ class PrefixBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditF
) )
tenant = DynamicModelChoiceField( tenant = DynamicModelChoiceField(
queryset=Tenant.objects.all(), queryset=Tenant.objects.all(),
required=False, required=False
widget=APISelect(
api_url="/api/tenancy/tenants/"
)
) )
status = forms.ChoiceField( status = forms.ChoiceField(
choices=add_blank_choice(PrefixStatusChoices), choices=add_blank_choice(PrefixStatusChoices),
@ -479,10 +451,7 @@ class PrefixBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditF
) )
role = DynamicModelChoiceField( role = DynamicModelChoiceField(
queryset=Role.objects.all(), queryset=Role.objects.all(),
required=False, required=False
widget=APISelect(
api_url="/api/ipam/roles/"
)
) )
is_pool = forms.NullBooleanField( is_pool = forms.NullBooleanField(
required=False, required=False,
@ -536,7 +505,6 @@ class PrefixFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm)
required=False, required=False,
label='VRF', label='VRF',
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/ipam/vrfs/",
null_option=True, null_option=True,
) )
) )
@ -550,7 +518,6 @@ class PrefixFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm)
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/regions/",
value_field="slug", value_field="slug",
filter_for={ filter_for={
'site': 'region' 'site': 'region'
@ -562,7 +529,6 @@ class PrefixFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm)
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/sites/",
value_field="slug", value_field="slug",
null_option=True, null_option=True,
) )
@ -572,7 +538,6 @@ class PrefixFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm)
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/ipam/roles/",
value_field="slug", value_field="slug",
null_option=True, null_option=True,
) )
@ -603,17 +568,13 @@ class IPAddressForm(BootstrapMixin, TenancyForm, ReturnURLForm, CustomFieldModel
vrf = DynamicModelChoiceField( vrf = DynamicModelChoiceField(
queryset=VRF.objects.all(), queryset=VRF.objects.all(),
required=False, required=False,
label='VRF', label='VRF'
widget=APISelect(
api_url="/api/ipam/vrfs/"
)
) )
nat_site = DynamicModelChoiceField( nat_site = DynamicModelChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
required=False, required=False,
label='Site', label='Site',
widget=APISelect( widget=APISelect(
api_url="/api/dcim/sites/",
filter_for={ filter_for={
'nat_rack': 'site_id', 'nat_rack': 'site_id',
'nat_device': 'site_id' 'nat_device': 'site_id'
@ -625,7 +586,6 @@ class IPAddressForm(BootstrapMixin, TenancyForm, ReturnURLForm, CustomFieldModel
required=False, required=False,
label='Rack', label='Rack',
widget=APISelect( widget=APISelect(
api_url='/api/dcim/racks/',
display_field='display_name', display_field='display_name',
filter_for={ filter_for={
'nat_device': 'rack_id' 'nat_device': 'rack_id'
@ -640,19 +600,17 @@ class IPAddressForm(BootstrapMixin, TenancyForm, ReturnURLForm, CustomFieldModel
required=False, required=False,
label='Device', label='Device',
widget=APISelect( widget=APISelect(
api_url='/api/dcim/devices/',
display_field='display_name', display_field='display_name',
filter_for={ filter_for={
'nat_inside': 'device_id' 'nat_inside': 'device_id'
} }
) )
) )
nat_vrf = forms.ModelChoiceField( nat_vrf = DynamicModelChoiceField(
queryset=VRF.objects.all(), queryset=VRF.objects.all(),
required=False, required=False,
label='VRF', label='VRF',
widget=APISelect( widget=APISelect(
api_url="/api/ipam/vrfs/",
filter_for={ filter_for={
'nat_inside': 'vrf_id' 'nat_inside': 'vrf_id'
} }
@ -663,7 +621,6 @@ class IPAddressForm(BootstrapMixin, TenancyForm, ReturnURLForm, CustomFieldModel
required=False, required=False,
label='IP Address', label='IP Address',
widget=APISelect( widget=APISelect(
api_url='/api/ipam/ip-addresses/',
display_field='address' display_field='address'
) )
) )
@ -761,10 +718,7 @@ class IPAddressBulkAddForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
vrf = DynamicModelChoiceField( vrf = DynamicModelChoiceField(
queryset=VRF.objects.all(), queryset=VRF.objects.all(),
required=False, required=False,
label='VRF', label='VRF'
widget=APISelect(
api_url="/api/ipam/vrfs/"
)
) )
class Meta: class Meta:
@ -913,10 +867,7 @@ class IPAddressBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEd
vrf = DynamicModelChoiceField( vrf = DynamicModelChoiceField(
queryset=VRF.objects.all(), queryset=VRF.objects.all(),
required=False, required=False,
label='VRF', label='VRF'
widget=APISelect(
api_url="/api/ipam/vrfs/"
)
) )
mask_length = forms.IntegerField( mask_length = forms.IntegerField(
min_value=IPADDRESS_MASK_LENGTH_MIN, min_value=IPADDRESS_MASK_LENGTH_MIN,
@ -925,10 +876,7 @@ class IPAddressBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEd
) )
tenant = DynamicModelChoiceField( tenant = DynamicModelChoiceField(
queryset=Tenant.objects.all(), queryset=Tenant.objects.all(),
required=False, required=False
widget=APISelect(
api_url="/api/tenancy/tenants/"
)
) )
status = forms.ChoiceField( status = forms.ChoiceField(
choices=add_blank_choice(IPAddressStatusChoices), choices=add_blank_choice(IPAddressStatusChoices),
@ -960,10 +908,7 @@ class IPAddressAssignForm(BootstrapMixin, forms.Form):
queryset=VRF.objects.all(), queryset=VRF.objects.all(),
required=False, required=False,
label='VRF', label='VRF',
empty_label='Global', empty_label='Global'
widget=APISelect(
api_url="/api/ipam/vrfs/"
)
) )
q = forms.CharField( q = forms.CharField(
required=False, required=False,
@ -1007,7 +952,6 @@ class IPAddressFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterFo
required=False, required=False,
label='VRF', label='VRF',
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/ipam/vrfs/",
null_option=True, null_option=True,
) )
) )
@ -1038,10 +982,7 @@ class IPAddressFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterFo
class VLANGroupForm(BootstrapMixin, forms.ModelForm): class VLANGroupForm(BootstrapMixin, forms.ModelForm):
site = DynamicModelChoiceField( site = DynamicModelChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
required=False, required=False
widget=APISelect(
api_url="/api/dcim/sites/"
)
) )
slug = SlugField() slug = SlugField()
@ -1078,7 +1019,6 @@ class VLANGroupFilterForm(BootstrapMixin, forms.Form):
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/regions/",
value_field="slug", value_field="slug",
filter_for={ filter_for={
'site': 'region', 'site': 'region',
@ -1090,7 +1030,6 @@ class VLANGroupFilterForm(BootstrapMixin, forms.Form):
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/sites/",
value_field="slug", value_field="slug",
null_option=True, null_option=True,
) )
@ -1106,7 +1045,6 @@ class VLANForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
queryset=Site.objects.all(), queryset=Site.objects.all(),
required=False, required=False,
widget=APISelect( widget=APISelect(
api_url="/api/dcim/sites/",
filter_for={ filter_for={
'group': 'site_id' 'group': 'site_id'
}, },
@ -1117,17 +1055,11 @@ class VLANForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
) )
group = DynamicModelChoiceField( group = DynamicModelChoiceField(
queryset=VLANGroup.objects.all(), queryset=VLANGroup.objects.all(),
required=False, required=False
widget=APISelect(
api_url='/api/ipam/vlan-groups/',
)
) )
role = DynamicModelChoiceField( role = DynamicModelChoiceField(
queryset=Role.objects.all(), queryset=Role.objects.all(),
required=False, required=False
widget=APISelect(
api_url="/api/ipam/roles/"
)
) )
tags = TagField(required=False) tags = TagField(required=False)
@ -1222,24 +1154,15 @@ class VLANBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditFor
) )
site = DynamicModelChoiceField( site = DynamicModelChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
required=False, required=False
widget=APISelect(
api_url="/api/dcim/sites/"
)
) )
group = DynamicModelChoiceField( group = DynamicModelChoiceField(
queryset=VLANGroup.objects.all(), queryset=VLANGroup.objects.all(),
required=False, required=False
widget=APISelect(
api_url="/api/ipam/vlan-groups/"
)
) )
tenant = DynamicModelChoiceField( tenant = DynamicModelChoiceField(
queryset=Tenant.objects.all(), queryset=Tenant.objects.all(),
required=False, required=False
widget=APISelect(
api_url="/api/tenancy/tenants/"
)
) )
status = forms.ChoiceField( status = forms.ChoiceField(
choices=add_blank_choice(VLANStatusChoices), choices=add_blank_choice(VLANStatusChoices),
@ -1248,10 +1171,7 @@ class VLANBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditFor
) )
role = DynamicModelChoiceField( role = DynamicModelChoiceField(
queryset=Role.objects.all(), queryset=Role.objects.all(),
required=False, required=False
widget=APISelect(
api_url="/api/ipam/roles/"
)
) )
description = forms.CharField( description = forms.CharField(
max_length=100, max_length=100,
@ -1276,7 +1196,6 @@ class VLANFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/regions/",
value_field="slug", value_field="slug",
filter_for={ filter_for={
'site': 'region', 'site': 'region',
@ -1289,7 +1208,6 @@ class VLANFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/sites/",
value_field="slug", value_field="slug",
null_option=True, null_option=True,
) )
@ -1299,7 +1217,6 @@ class VLANFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
required=False, required=False,
label='VLAN group', label='VLAN group',
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/ipam/vlan-groups/",
null_option=True, null_option=True,
) )
) )
@ -1313,7 +1230,6 @@ class VLANFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/ipam/roles/",
value_field="slug", value_field="slug",
null_option=True, null_option=True,
) )

View File

@ -72,10 +72,7 @@ class SecretRoleCSVForm(forms.ModelForm):
class SecretForm(BootstrapMixin, CustomFieldModelForm): class SecretForm(BootstrapMixin, CustomFieldModelForm):
device = DynamicModelChoiceField( device = DynamicModelChoiceField(
queryset=Device.objects.all(), queryset=Device.objects.all()
widget=APISelect(
api_url="/api/dcim/devices/"
)
) )
plaintext = forms.CharField( plaintext = forms.CharField(
max_length=SECRET_PLAINTEXT_MAX_LENGTH, max_length=SECRET_PLAINTEXT_MAX_LENGTH,
@ -94,10 +91,7 @@ class SecretForm(BootstrapMixin, CustomFieldModelForm):
widget=forms.PasswordInput() widget=forms.PasswordInput()
) )
role = DynamicModelChoiceField( role = DynamicModelChoiceField(
queryset=SecretRole.objects.all(), queryset=SecretRole.objects.all()
widget=APISelect(
api_url="/api/secrets/secret-roles/"
)
) )
tags = TagField( tags = TagField(
required=False required=False
@ -166,10 +160,7 @@ class SecretBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditF
) )
role = DynamicModelChoiceField( role = DynamicModelChoiceField(
queryset=SecretRole.objects.all(), queryset=SecretRole.objects.all(),
required=False, required=False
widget=APISelect(
api_url="/api/secrets/secret-roles/"
)
) )
name = forms.CharField( name = forms.CharField(
max_length=100, max_length=100,
@ -193,7 +184,6 @@ class SecretFilterForm(BootstrapMixin, CustomFieldFilterForm):
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/secrets/secret-roles/",
value_field="slug", value_field="slug",
) )
) )

View File

@ -44,10 +44,7 @@ class TenantForm(BootstrapMixin, CustomFieldModelForm):
slug = SlugField() slug = SlugField()
group = DynamicModelChoiceField( group = DynamicModelChoiceField(
queryset=TenantGroup.objects.all(), queryset=TenantGroup.objects.all(),
required=False, required=False
widget=APISelect(
api_url="/api/tenancy/tenant-groups/"
)
) )
comments = CommentField() comments = CommentField()
tags = TagField( tags = TagField(
@ -89,10 +86,7 @@ class TenantBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditF
) )
group = DynamicModelChoiceField( group = DynamicModelChoiceField(
queryset=TenantGroup.objects.all(), queryset=TenantGroup.objects.all(),
required=False, required=False
widget=APISelect(
api_url="/api/tenancy/tenant-groups/"
)
) )
class Meta: class Meta:
@ -112,7 +106,6 @@ class TenantFilterForm(BootstrapMixin, CustomFieldFilterForm):
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/tenancy/tenant-groups/",
value_field="slug", value_field="slug",
null_option=True, null_option=True,
) )
@ -129,7 +122,6 @@ class TenancyForm(forms.Form):
queryset=TenantGroup.objects.all(), queryset=TenantGroup.objects.all(),
required=False, required=False,
widget=APISelect( widget=APISelect(
api_url="/api/tenancy/tenant-groups/",
filter_for={ filter_for={
'tenant': 'group_id', 'tenant': 'group_id',
}, },
@ -140,10 +132,7 @@ class TenancyForm(forms.Form):
) )
tenant = DynamicModelChoiceField( tenant = DynamicModelChoiceField(
queryset=Tenant.objects.all(), queryset=Tenant.objects.all(),
required=False, required=False
widget=APISelect(
api_url='/api/tenancy/tenants/'
)
) )
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@ -164,7 +153,6 @@ class TenancyFilterForm(forms.Form):
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/tenancy/tenant-groups/",
value_field="slug", value_field="slug",
null_option=True, null_option=True,
filter_for={ filter_for={
@ -177,7 +165,6 @@ class TenancyFilterForm(forms.Form):
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/tenancy/tenants/",
value_field="slug", value_field="slug",
null_option=True, null_option=True,
) )

View File

@ -10,6 +10,7 @@ from django.conf import settings
from django.contrib.postgres.forms.jsonb import JSONField as _JSONField, InvalidJSONInput from django.contrib.postgres.forms.jsonb import JSONField as _JSONField, InvalidJSONInput
from django.db.models import Count from django.db.models import Count
from django.forms import BoundField from django.forms import BoundField
from django.urls import reverse
from .choices import unpack_grouped_choices from .choices import unpack_grouped_choices
from .constants import * from .constants import *
@ -252,7 +253,7 @@ class APISelect(SelectWithDisabled):
""" """
A select widget populated via an API call A select widget populated via an API call
:param api_url: API URL :param api_url: API endpoint URL. Required if not set automatically by the parent field.
:param display_field: (Optional) Field to display for child in selection list. Defaults to `name`. :param display_field: (Optional) Field to display for child in selection list. Defaults to `name`.
:param value_field: (Optional) Field to use for the option value in selection list. Defaults to `id`. :param value_field: (Optional) Field to use for the option value in selection list. Defaults to `id`.
:param disabled_indicator: (Optional) Mark option as disabled if this field equates true. :param disabled_indicator: (Optional) Mark option as disabled if this field equates true.
@ -269,7 +270,7 @@ class APISelect(SelectWithDisabled):
""" """
def __init__( def __init__(
self, self,
api_url, api_url=None,
display_field=None, display_field=None,
value_field=None, value_field=None,
disabled_indicator=None, disabled_indicator=None,
@ -285,7 +286,8 @@ class APISelect(SelectWithDisabled):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.attrs['class'] = 'netbox-select2-api' self.attrs['class'] = 'netbox-select2-api'
self.attrs['data-url'] = '/{}{}'.format(settings.BASE_PATH, api_url.lstrip('/')) # Inject BASE_PATH if api_url:
self.attrs['data-url'] = '/{}{}'.format(settings.BASE_PATH, api_url.lstrip('/')) # Inject BASE_PATH
if full: if full:
self.attrs['data-full'] = full self.attrs['data-full'] = full
if display_field: if display_field:
@ -566,6 +568,10 @@ class TagFilterField(forms.MultipleChoiceField):
class DynamicModelChoiceMixin: class DynamicModelChoiceMixin:
filter = django_filters.ModelChoiceFilter filter = django_filters.ModelChoiceFilter
widget = APISelect
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def get_bound_field(self, form, field_name): def get_bound_field(self, form, field_name):
bound_field = BoundField(form, self, field_name) bound_field = BoundField(form, self, field_name)
@ -579,6 +585,14 @@ class DynamicModelChoiceMixin:
else: else:
self.queryset = self.queryset.none() self.queryset = self.queryset.none()
# Set the data URL on the APISelect widget (if not already set)
widget = bound_field.field.widget
if not widget.attrs.get('data-url'):
app_label = self.queryset.model._meta.app_label
model_name = self.queryset.model._meta.model_name
data_url = reverse('{}-api:{}-list'.format(app_label, model_name))
widget.attrs['data-url'] = data_url
return bound_field return bound_field
@ -595,6 +609,7 @@ class DynamicModelMultipleChoiceField(DynamicModelChoiceMixin, forms.ModelMultip
A multiple-choice version of DynamicModelChoiceField. A multiple-choice version of DynamicModelChoiceField.
""" """
filter = django_filters.ModelMultipleChoiceFilter filter = django_filters.ModelMultipleChoiceFilter
widget = APISelectMultiple
class LaxURLField(forms.URLField): class LaxURLField(forms.URLField):

View File

@ -9,7 +9,7 @@ from dcim.models import Device, DeviceRole, Interface, Platform, Rack, Region, S
from extras.forms import ( from extras.forms import (
AddRemoveTagsForm, CustomFieldBulkEditForm, CustomFieldModelCSVForm, CustomFieldModelForm, CustomFieldFilterForm, AddRemoveTagsForm, CustomFieldBulkEditForm, CustomFieldModelCSVForm, CustomFieldModelForm, CustomFieldFilterForm,
) )
from ipam.models import IPAddress, VLANGroup, VLAN from ipam.models import IPAddress, VLAN
from tenancy.forms import TenancyFilterForm, TenancyForm from tenancy.forms import TenancyFilterForm, TenancyForm
from tenancy.models import Tenant from tenancy.models import Tenant
from utilities.forms import ( from utilities.forms import (
@ -77,24 +77,15 @@ class ClusterGroupCSVForm(forms.ModelForm):
class ClusterForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): class ClusterForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
type = DynamicModelChoiceField( type = DynamicModelChoiceField(
queryset=ClusterType.objects.all(), queryset=ClusterType.objects.all()
widget=APISelect(
api_url="/api/virtualization/cluster-types/"
)
) )
group = DynamicModelChoiceField( group = DynamicModelChoiceField(
queryset=ClusterGroup.objects.all(), queryset=ClusterGroup.objects.all(),
required=False, required=False
widget=APISelect(
api_url="/api/virtualization/cluster-groups/"
)
) )
site = DynamicModelChoiceField( site = DynamicModelChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
required=False, required=False
widget=APISelect(
api_url="/api/dcim/sites/"
)
) )
comments = CommentField() comments = CommentField()
tags = TagField( tags = TagField(
@ -157,31 +148,19 @@ class ClusterBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEdit
) )
type = DynamicModelChoiceField( type = DynamicModelChoiceField(
queryset=ClusterType.objects.all(), queryset=ClusterType.objects.all(),
required=False, required=False
widget=APISelect(
api_url="/api/virtualization/cluster-types/"
)
) )
group = DynamicModelChoiceField( group = DynamicModelChoiceField(
queryset=ClusterGroup.objects.all(), queryset=ClusterGroup.objects.all(),
required=False, required=False
widget=APISelect(
api_url="/api/virtualization/cluster-groups/"
)
) )
tenant = DynamicModelChoiceField( tenant = DynamicModelChoiceField(
queryset=Tenant.objects.all(), queryset=Tenant.objects.all(),
required=False, required=False
widget=APISelect(
api_url="/api/tenancy/tenants/"
)
) )
site = DynamicModelChoiceField( site = DynamicModelChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
required=False, required=False
widget=APISelect(
api_url="/api/dcim/sites/"
)
) )
comments = CommentField( comments = CommentField(
widget=SmallTextarea, widget=SmallTextarea,
@ -205,7 +184,6 @@ class ClusterFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/virtualization/cluster-types/",
value_field='slug', value_field='slug',
) )
) )
@ -214,7 +192,6 @@ class ClusterFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/regions/",
value_field="slug", value_field="slug",
filter_for={ filter_for={
'site': 'region' 'site': 'region'
@ -226,7 +203,6 @@ class ClusterFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/dcim/sites/",
value_field='slug', value_field='slug',
null_option=True, null_option=True,
) )
@ -236,7 +212,6 @@ class ClusterFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/virtualization/cluster-groups/",
value_field='slug', value_field='slug',
null_option=True, null_option=True,
) )
@ -249,7 +224,6 @@ class ClusterAddDevicesForm(BootstrapMixin, forms.Form):
queryset=Region.objects.all(), queryset=Region.objects.all(),
required=False, required=False,
widget=APISelect( widget=APISelect(
api_url="/api/dcim/regions/",
filter_for={ filter_for={
"site": "region_id", "site": "region_id",
}, },
@ -262,7 +236,6 @@ class ClusterAddDevicesForm(BootstrapMixin, forms.Form):
queryset=Site.objects.all(), queryset=Site.objects.all(),
required=False, required=False,
widget=APISelect( widget=APISelect(
api_url='/api/dcim/sites/',
filter_for={ filter_for={
"rack": "site_id", "rack": "site_id",
"devices": "site_id", "devices": "site_id",
@ -273,7 +246,6 @@ class ClusterAddDevicesForm(BootstrapMixin, forms.Form):
queryset=Rack.objects.all(), queryset=Rack.objects.all(),
required=False, required=False,
widget=APISelect( widget=APISelect(
api_url='/api/dcim/racks/',
filter_for={ filter_for={
"devices": "rack_id" "devices": "rack_id"
}, },
@ -285,7 +257,6 @@ class ClusterAddDevicesForm(BootstrapMixin, forms.Form):
devices = DynamicModelMultipleChoiceField( devices = DynamicModelMultipleChoiceField(
queryset=Device.objects.filter(cluster__isnull=True), queryset=Device.objects.filter(cluster__isnull=True),
widget=APISelectMultiple( widget=APISelectMultiple(
api_url='/api/dcim/devices/',
display_field='display_name', display_field='display_name',
disabled_indicator='cluster' disabled_indicator='cluster'
) )
@ -334,7 +305,6 @@ class VirtualMachineForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
queryset=ClusterGroup.objects.all(), queryset=ClusterGroup.objects.all(),
required=False, required=False,
widget=APISelect( widget=APISelect(
api_url='/api/virtualization/cluster-groups/',
filter_for={ filter_for={
"cluster": "group_id", "cluster": "group_id",
}, },
@ -344,16 +314,12 @@ class VirtualMachineForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
) )
) )
cluster = DynamicModelChoiceField( cluster = DynamicModelChoiceField(
queryset=Cluster.objects.all(), queryset=Cluster.objects.all()
widget=APISelect(
api_url='/api/virtualization/clusters/'
)
) )
role = DynamicModelChoiceField( role = DynamicModelChoiceField(
queryset=DeviceRole.objects.all(), queryset=DeviceRole.objects.all(),
required=False, required=False,
widget=APISelect( widget=APISelect(
api_url="/api/dcim/device-roles/",
additional_query_params={ additional_query_params={
"vm_role": "True" "vm_role": "True"
} }
@ -361,10 +327,7 @@ class VirtualMachineForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
) )
platform = DynamicModelChoiceField( platform = DynamicModelChoiceField(
queryset=Platform.objects.all(), queryset=Platform.objects.all(),
required=False, required=False
widget=APISelect(
api_url='/api/dcim/platforms/'
)
) )
tags = TagField( tags = TagField(
required=False required=False
@ -499,10 +462,7 @@ class VirtualMachineBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldB
) )
cluster = DynamicModelChoiceField( cluster = DynamicModelChoiceField(
queryset=Cluster.objects.all(), queryset=Cluster.objects.all(),
required=False, required=False
widget=APISelect(
api_url='/api/virtualization/clusters/'
)
) )
role = DynamicModelChoiceField( role = DynamicModelChoiceField(
queryset=DeviceRole.objects.filter( queryset=DeviceRole.objects.filter(
@ -510,7 +470,6 @@ class VirtualMachineBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldB
), ),
required=False, required=False,
widget=APISelect( widget=APISelect(
api_url="/api/dcim/device-roles/",
additional_query_params={ additional_query_params={
"vm_role": "True" "vm_role": "True"
} }
@ -518,17 +477,11 @@ class VirtualMachineBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldB
) )
tenant = DynamicModelChoiceField( tenant = DynamicModelChoiceField(
queryset=Tenant.objects.all(), queryset=Tenant.objects.all(),
required=False, required=False
widget=APISelect(
api_url='/api/tenancy/tenants/'
)
) )
platform = DynamicModelChoiceField( platform = DynamicModelChoiceField(
queryset=Platform.objects.all(), queryset=Platform.objects.all(),
required=False, required=False
widget=APISelect(
api_url='/api/dcim/platforms/'
)
) )
vcpus = forms.IntegerField( vcpus = forms.IntegerField(
required=False, required=False,
@ -568,7 +521,6 @@ class VirtualMachineFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFil
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url='/api/virtualization/cluster-groups/',
value_field="slug", value_field="slug",
null_option=True, null_option=True,
) )
@ -578,7 +530,6 @@ class VirtualMachineFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFil
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url='/api/virtualization/cluster-types/',
value_field="slug", value_field="slug",
null_option=True, null_option=True,
) )
@ -586,17 +537,13 @@ class VirtualMachineFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFil
cluster_id = DynamicModelMultipleChoiceField( cluster_id = DynamicModelMultipleChoiceField(
queryset=Cluster.objects.all(), queryset=Cluster.objects.all(),
required=False, required=False,
label='Cluster', label='Cluster'
widget=APISelectMultiple(
api_url='/api/virtualization/clusters/',
)
) )
region = DynamicModelMultipleChoiceField( region = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(), queryset=Region.objects.all(),
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url='/api/dcim/regions/',
value_field="slug", value_field="slug",
filter_for={ filter_for={
'site': 'region' 'site': 'region'
@ -608,7 +555,6 @@ class VirtualMachineFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFil
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url='/api/dcim/sites/',
value_field="slug", value_field="slug",
null_option=True, null_option=True,
) )
@ -618,7 +564,6 @@ class VirtualMachineFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFil
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url='/api/dcim/device-roles/',
value_field="slug", value_field="slug",
null_option=True, null_option=True,
additional_query_params={ additional_query_params={
@ -636,7 +581,6 @@ class VirtualMachineFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFil
to_field_name='slug', to_field_name='slug',
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url='/api/dcim/platforms/',
value_field="slug", value_field="slug",
null_option=True, null_option=True,
) )
@ -657,7 +601,6 @@ class InterfaceForm(BootstrapMixin, forms.ModelForm):
queryset=VLAN.objects.all(), queryset=VLAN.objects.all(),
required=False, required=False,
widget=APISelect( widget=APISelect(
api_url="/api/ipam/vlans/",
display_field='display_name', display_field='display_name',
full=True, full=True,
additional_query_params={ additional_query_params={
@ -669,7 +612,6 @@ class InterfaceForm(BootstrapMixin, forms.ModelForm):
queryset=VLAN.objects.all(), queryset=VLAN.objects.all(),
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/ipam/vlans/",
display_field='display_name', display_field='display_name',
full=True, full=True,
additional_query_params={ additional_query_params={
@ -766,7 +708,6 @@ class InterfaceCreateForm(BootstrapMixin, forms.Form):
queryset=VLAN.objects.all(), queryset=VLAN.objects.all(),
required=False, required=False,
widget=APISelect( widget=APISelect(
api_url="/api/ipam/vlans/",
display_field='display_name', display_field='display_name',
full=True, full=True,
additional_query_params={ additional_query_params={
@ -778,7 +719,6 @@ class InterfaceCreateForm(BootstrapMixin, forms.Form):
queryset=VLAN.objects.all(), queryset=VLAN.objects.all(),
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/ipam/vlans/",
display_field='display_name', display_field='display_name',
full=True, full=True,
additional_query_params={ additional_query_params={
@ -836,7 +776,6 @@ class InterfaceBulkEditForm(BootstrapMixin, BulkEditForm):
queryset=VLAN.objects.all(), queryset=VLAN.objects.all(),
required=False, required=False,
widget=APISelect( widget=APISelect(
api_url="/api/ipam/vlans/",
display_field='display_name', display_field='display_name',
full=True, full=True,
additional_query_params={ additional_query_params={
@ -848,7 +787,6 @@ class InterfaceBulkEditForm(BootstrapMixin, BulkEditForm):
queryset=VLAN.objects.all(), queryset=VLAN.objects.all(),
required=False, required=False,
widget=APISelectMultiple( widget=APISelectMultiple(
api_url="/api/ipam/vlans/",
display_field='display_name', display_field='display_name',
full=True, full=True,
additional_query_params={ additional_query_params={