mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-17 12:42:52 -06:00
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:
commit
00afe7aa94
@ -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
@ -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",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -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,
|
||||||
)
|
)
|
||||||
|
@ -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",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -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,
|
||||||
)
|
)
|
||||||
|
@ -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):
|
||||||
|
@ -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={
|
||||||
|
Loading…
Reference in New Issue
Block a user