mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
IPAM Select2 forms and changelog
This commit is contained in:
@ -1,7 +1,6 @@
|
||||
from django import forms
|
||||
from django.core.exceptions import MultipleObjectsReturned
|
||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||
from django.db.models import Count
|
||||
from taggit.forms import TagField
|
||||
|
||||
from dcim.models import Site, Rack, Device, Interface
|
||||
@ -9,9 +8,9 @@ from extras.forms import AddRemoveTagsForm, CustomFieldForm, CustomFieldBulkEdit
|
||||
from tenancy.forms import TenancyForm
|
||||
from tenancy.models import Tenant
|
||||
from utilities.forms import (
|
||||
AnnotatedMultipleChoiceField, APISelect, BootstrapMixin, BulkEditNullBooleanSelect, ChainedModelChoiceField,
|
||||
CSVChoiceField, ExpandableIPAddressField, FilterChoiceField, FlexibleModelChoiceField, Livesearch, ReturnURLForm,
|
||||
SlugField, add_blank_choice,
|
||||
add_blank_choice, APISelect, APISelectMultiple, BootstrapMixin, BulkEditNullBooleanSelect, ChainedModelChoiceField,
|
||||
CSVChoiceField, ExpandableIPAddressField, FilterChoiceField, FlexibleModelChoiceField, ReturnURLForm, SlugField,
|
||||
StaticSelect2, StaticSelect2Multiple, BOOLEAN_WITH_BLANK_CHOICES
|
||||
)
|
||||
from virtualization.models import VirtualMachine
|
||||
from .constants import (
|
||||
@ -77,7 +76,10 @@ class VRFBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm
|
||||
)
|
||||
tenant = forms.ModelChoiceField(
|
||||
queryset=Tenant.objects.all(),
|
||||
required=False
|
||||
required=False,
|
||||
widget=APISelect(
|
||||
api_url="/api/tenancy/tenants/"
|
||||
)
|
||||
)
|
||||
enforce_unique = forms.NullBooleanField(
|
||||
required=False,
|
||||
@ -102,11 +104,14 @@ class VRFFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
||||
label='Search'
|
||||
)
|
||||
tenant = FilterChoiceField(
|
||||
queryset=Tenant.objects.annotate(
|
||||
filter_count=Count('vrfs')
|
||||
),
|
||||
queryset=Tenant.objects.all(),
|
||||
to_field_name='slug',
|
||||
null_label='-- None --'
|
||||
null_label='-- None --',
|
||||
widget=APISelectMultiple(
|
||||
api_url="/api/tenancy/tenants/",
|
||||
value_field="slug",
|
||||
null_option=True,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@ -139,12 +144,8 @@ class RIRFilterForm(BootstrapMixin, forms.Form):
|
||||
is_private = forms.NullBooleanField(
|
||||
required=False,
|
||||
label='Private',
|
||||
widget=forms.Select(
|
||||
choices=[
|
||||
('', '---------'),
|
||||
('True', 'Yes'),
|
||||
('False', 'No'),
|
||||
]
|
||||
widget=StaticSelect2(
|
||||
choices=BOOLEAN_WITH_BLANK_CHOICES
|
||||
)
|
||||
)
|
||||
|
||||
@ -168,6 +169,11 @@ class AggregateForm(BootstrapMixin, CustomFieldForm):
|
||||
'rir': "Regional Internet Registry responsible for this prefix",
|
||||
'date_added': "Format: YYYY-MM-DD",
|
||||
}
|
||||
widgets = {
|
||||
'rir': APISelect(
|
||||
api_url="/api/ipam/rirs/"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
class AggregateCSVForm(forms.ModelForm):
|
||||
@ -193,7 +199,10 @@ class AggregateBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEd
|
||||
rir = forms.ModelChoiceField(
|
||||
queryset=RIR.objects.all(),
|
||||
required=False,
|
||||
label='RIR'
|
||||
label='RIR',
|
||||
widget=APISelect(
|
||||
api_url="/api/ipam/rirs/"
|
||||
)
|
||||
)
|
||||
date_added = forms.DateField(
|
||||
required=False
|
||||
@ -218,12 +227,17 @@ class AggregateFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
||||
family = forms.ChoiceField(
|
||||
required=False,
|
||||
choices=IP_FAMILY_CHOICES,
|
||||
label='Address family'
|
||||
label='Address family',
|
||||
widget=StaticSelect2()
|
||||
)
|
||||
rir = FilterChoiceField(
|
||||
queryset=RIR.objects.annotate(filter_count=Count('aggregates')),
|
||||
queryset=RIR.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='RIR'
|
||||
label='RIR',
|
||||
widget=APISelectMultiple(
|
||||
api_url="/api/ipam/rirs/",
|
||||
value_field="slug",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@ -261,9 +275,13 @@ class PrefixForm(BootstrapMixin, TenancyForm, CustomFieldForm):
|
||||
queryset=Site.objects.all(),
|
||||
required=False,
|
||||
label='Site',
|
||||
widget=forms.Select(
|
||||
widget=APISelect(
|
||||
api_url="/api/dcim/sites/",
|
||||
filter_for={
|
||||
'vlan_group': 'site_id',
|
||||
'vlan': 'site_id',
|
||||
},
|
||||
attrs={
|
||||
'filter-for': 'vlan_group',
|
||||
'nullable': 'true',
|
||||
}
|
||||
)
|
||||
@ -276,9 +294,11 @@ class PrefixForm(BootstrapMixin, TenancyForm, CustomFieldForm):
|
||||
required=False,
|
||||
label='VLAN group',
|
||||
widget=APISelect(
|
||||
api_url='/api/ipam/vlan-groups/?site_id={{site}}',
|
||||
api_url='/api/ipam/vlan-groups/',
|
||||
filter_for={
|
||||
'vlan': 'group_id'
|
||||
},
|
||||
attrs={
|
||||
'filter-for': 'vlan',
|
||||
'nullable': 'true',
|
||||
}
|
||||
)
|
||||
@ -292,7 +312,7 @@ class PrefixForm(BootstrapMixin, TenancyForm, CustomFieldForm):
|
||||
required=False,
|
||||
label='VLAN',
|
||||
widget=APISelect(
|
||||
api_url='/api/ipam/vlans/?site_id={{site}}&group_id={{vlan_group}}',
|
||||
api_url='/api/ipam/vlans/',
|
||||
display_field='display_name'
|
||||
)
|
||||
)
|
||||
@ -304,6 +324,15 @@ class PrefixForm(BootstrapMixin, TenancyForm, CustomFieldForm):
|
||||
'prefix', 'vrf', 'site', 'vlan', 'status', 'role', 'is_pool', 'description', 'tenant_group', 'tenant',
|
||||
'tags',
|
||||
]
|
||||
widgets = {
|
||||
'vrf': APISelect(
|
||||
api_url="/api/ipam/vrfs/"
|
||||
),
|
||||
'status': StaticSelect2(),
|
||||
'role': APISelect(
|
||||
api_url="/api/ipam/roles/"
|
||||
)
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
@ -415,12 +444,18 @@ class PrefixBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditF
|
||||
)
|
||||
site = forms.ModelChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
required=False
|
||||
required=False,
|
||||
widget=APISelect(
|
||||
api_url="/api/dcim/sites/"
|
||||
)
|
||||
)
|
||||
vrf = forms.ModelChoiceField(
|
||||
queryset=VRF.objects.all(),
|
||||
required=False,
|
||||
label='VRF'
|
||||
label='VRF',
|
||||
widget=APISelect(
|
||||
api_url="/api/ipam/vrfs/"
|
||||
)
|
||||
)
|
||||
prefix_length = forms.IntegerField(
|
||||
min_value=1,
|
||||
@ -429,15 +464,22 @@ class PrefixBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditF
|
||||
)
|
||||
tenant = forms.ModelChoiceField(
|
||||
queryset=Tenant.objects.all(),
|
||||
required=False
|
||||
required=False,
|
||||
widget=APISelect(
|
||||
api_url="/api/tenancy/tenants/"
|
||||
)
|
||||
)
|
||||
status = forms.ChoiceField(
|
||||
choices=add_blank_choice(PREFIX_STATUS_CHOICES),
|
||||
required=False
|
||||
required=False,
|
||||
widget=StaticSelect2()
|
||||
)
|
||||
role = forms.ModelChoiceField(
|
||||
queryset=Role.objects.all(),
|
||||
required=False
|
||||
required=False,
|
||||
widget=APISelect(
|
||||
api_url="/api/ipam/roles/"
|
||||
)
|
||||
)
|
||||
is_pool = forms.NullBooleanField(
|
||||
required=False,
|
||||
@ -473,47 +515,60 @@ class PrefixFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
||||
family = forms.ChoiceField(
|
||||
required=False,
|
||||
choices=IP_FAMILY_CHOICES,
|
||||
label='Address family'
|
||||
label='Address family',
|
||||
widget=StaticSelect2()
|
||||
)
|
||||
mask_length = forms.ChoiceField(
|
||||
required=False,
|
||||
choices=PREFIX_MASK_LENGTH_CHOICES,
|
||||
label='Mask length'
|
||||
label='Mask length',
|
||||
widget=StaticSelect2()
|
||||
)
|
||||
vrf = FilterChoiceField(
|
||||
queryset=VRF.objects.annotate(
|
||||
filter_count=Count('prefixes')
|
||||
),
|
||||
queryset=VRF.objects.all(),
|
||||
to_field_name='rd',
|
||||
label='VRF',
|
||||
null_label='-- Global --'
|
||||
null_label='-- Global --',
|
||||
widget=APISelectMultiple(
|
||||
api_url="/api/ipam/vrfs/",
|
||||
value_field="slug",
|
||||
null_option=True,
|
||||
)
|
||||
)
|
||||
tenant = FilterChoiceField(
|
||||
queryset=Tenant.objects.annotate(
|
||||
filter_count=Count('prefixes')
|
||||
),
|
||||
queryset=Tenant.objects.all(),
|
||||
to_field_name='slug',
|
||||
null_label='-- None --'
|
||||
null_label='-- None --',
|
||||
widget=APISelectMultiple(
|
||||
api_url="/api/tenancy/tenants/",
|
||||
value_field="slug",
|
||||
null_option=True,
|
||||
)
|
||||
)
|
||||
status = AnnotatedMultipleChoiceField(
|
||||
status = forms.MultipleChoiceField(
|
||||
choices=PREFIX_STATUS_CHOICES,
|
||||
annotate=Prefix.objects.all(),
|
||||
annotate_field='status',
|
||||
required=False
|
||||
required=False,
|
||||
widget=StaticSelect2Multiple()
|
||||
)
|
||||
site = FilterChoiceField(
|
||||
queryset=Site.objects.annotate(
|
||||
filter_count=Count('prefixes')
|
||||
),
|
||||
queryset=Site.objects.all(),
|
||||
to_field_name='slug',
|
||||
null_label='-- None --'
|
||||
null_label='-- None --',
|
||||
widget=APISelectMultiple(
|
||||
api_url="/api/dcim/sites/",
|
||||
value_field="slug",
|
||||
null_option=True,
|
||||
)
|
||||
)
|
||||
role = FilterChoiceField(
|
||||
queryset=Role.objects.annotate(
|
||||
filter_count=Count('prefixes')
|
||||
),
|
||||
queryset=Role.objects.all(),
|
||||
to_field_name='slug',
|
||||
null_label='-- None --'
|
||||
null_label='-- None --',
|
||||
widget=APISelectMultiple(
|
||||
api_url="/api/ipam/roles/",
|
||||
value_field="slug",
|
||||
null_option=True,
|
||||
)
|
||||
)
|
||||
expand = forms.BooleanField(
|
||||
required=False,
|
||||
@ -534,9 +589,11 @@ class IPAddressForm(BootstrapMixin, TenancyForm, ReturnURLForm, CustomFieldForm)
|
||||
queryset=Site.objects.all(),
|
||||
required=False,
|
||||
label='Site',
|
||||
widget=forms.Select(
|
||||
attrs={
|
||||
'filter-for': 'nat_rack'
|
||||
widget=APISelect(
|
||||
api_url="/api/dcim/sites/",
|
||||
filter_for={
|
||||
'nat_rack': 'site_id',
|
||||
'nat_device': 'site_id'
|
||||
}
|
||||
)
|
||||
)
|
||||
@ -548,10 +605,12 @@ class IPAddressForm(BootstrapMixin, TenancyForm, ReturnURLForm, CustomFieldForm)
|
||||
required=False,
|
||||
label='Rack',
|
||||
widget=APISelect(
|
||||
api_url='/api/dcim/racks/?site_id={{nat_site}}',
|
||||
api_url='/api/dcim/racks/',
|
||||
display_field='display_name',
|
||||
filter_for={
|
||||
'nat_device': 'rack_id'
|
||||
},
|
||||
attrs={
|
||||
'filter-for': 'nat_device',
|
||||
'nullable': 'true'
|
||||
}
|
||||
)
|
||||
@ -565,9 +624,11 @@ class IPAddressForm(BootstrapMixin, TenancyForm, ReturnURLForm, CustomFieldForm)
|
||||
required=False,
|
||||
label='Device',
|
||||
widget=APISelect(
|
||||
api_url='/api/dcim/devices/?site_id={{nat_site}}&rack_id={{nat_rack}}',
|
||||
api_url='/api/dcim/devices/',
|
||||
display_field='display_name',
|
||||
attrs={'filter-for': 'nat_inside'}
|
||||
filter_for={
|
||||
'nat_inside': 'device_id'
|
||||
}
|
||||
)
|
||||
)
|
||||
nat_inside = ChainedModelChoiceField(
|
||||
@ -578,20 +639,10 @@ class IPAddressForm(BootstrapMixin, TenancyForm, ReturnURLForm, CustomFieldForm)
|
||||
required=False,
|
||||
label='IP Address',
|
||||
widget=APISelect(
|
||||
api_url='/api/ipam/ip-addresses/?device_id={{nat_device}}',
|
||||
api_url='/api/ipam/ip-addresses/',
|
||||
display_field='address'
|
||||
)
|
||||
)
|
||||
livesearch = forms.CharField(
|
||||
required=False,
|
||||
label='Search',
|
||||
widget=Livesearch(
|
||||
query_key='q',
|
||||
query_url='ipam-api:ipaddress-list',
|
||||
field_to_update='nat_inside',
|
||||
obj_label='address'
|
||||
)
|
||||
)
|
||||
primary_for_parent = forms.BooleanField(
|
||||
required=False,
|
||||
label='Make this the primary IP for the device/VM'
|
||||
@ -606,6 +657,13 @@ class IPAddressForm(BootstrapMixin, TenancyForm, ReturnURLForm, CustomFieldForm)
|
||||
'address', 'vrf', 'status', 'role', 'description', 'interface', 'primary_for_parent', 'nat_site',
|
||||
'nat_rack', 'nat_inside', 'tenant_group', 'tenant', 'tags',
|
||||
]
|
||||
widgets = {
|
||||
'status': StaticSelect2(),
|
||||
'role': StaticSelect2(),
|
||||
'vrf': APISelect(
|
||||
api_url="/api/ipam/vrfs/"
|
||||
)
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
@ -685,6 +743,13 @@ class IPAddressBulkAddForm(BootstrapMixin, TenancyForm, CustomFieldForm):
|
||||
fields = [
|
||||
'address', 'vrf', 'status', 'role', 'description', 'tenant_group', 'tenant',
|
||||
]
|
||||
widgets = {
|
||||
'status': StaticSelect2(),
|
||||
'role': StaticSelect2(),
|
||||
'vrf': APISelect(
|
||||
api_url="/api/ipam/vrfs/"
|
||||
)
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
@ -822,7 +887,10 @@ class IPAddressBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEd
|
||||
vrf = forms.ModelChoiceField(
|
||||
queryset=VRF.objects.all(),
|
||||
required=False,
|
||||
label='VRF'
|
||||
label='VRF',
|
||||
widget=APISelect(
|
||||
api_url="/api/ipam/vrfs/"
|
||||
)
|
||||
)
|
||||
mask_length = forms.IntegerField(
|
||||
min_value=1,
|
||||
@ -831,15 +899,20 @@ class IPAddressBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEd
|
||||
)
|
||||
tenant = forms.ModelChoiceField(
|
||||
queryset=Tenant.objects.all(),
|
||||
required=False
|
||||
required=False,
|
||||
widget=APISelect(
|
||||
api_url="/api/tenancy/tenants/"
|
||||
)
|
||||
)
|
||||
status = forms.ChoiceField(
|
||||
choices=add_blank_choice(IPADDRESS_STATUS_CHOICES),
|
||||
required=False
|
||||
required=False,
|
||||
widget=StaticSelect2()
|
||||
)
|
||||
role = forms.ChoiceField(
|
||||
choices=add_blank_choice(IPADDRESS_ROLE_CHOICES),
|
||||
required=False
|
||||
required=False,
|
||||
widget=StaticSelect2()
|
||||
)
|
||||
description = forms.CharField(
|
||||
max_length=100, required=False
|
||||
@ -856,7 +929,10 @@ class IPAddressAssignForm(BootstrapMixin, forms.Form):
|
||||
queryset=VRF.objects.all(),
|
||||
required=False,
|
||||
label='VRF',
|
||||
empty_label='Global'
|
||||
empty_label='Global',
|
||||
widget=APISelect(
|
||||
api_url="/api/ipam/vrfs/"
|
||||
)
|
||||
)
|
||||
address = forms.CharField(
|
||||
label='IP Address'
|
||||
@ -881,39 +957,45 @@ class IPAddressFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
||||
family = forms.ChoiceField(
|
||||
required=False,
|
||||
choices=IP_FAMILY_CHOICES,
|
||||
label='Address family'
|
||||
label='Address family',
|
||||
widget=StaticSelect2()
|
||||
)
|
||||
mask_length = forms.ChoiceField(
|
||||
required=False,
|
||||
choices=IPADDRESS_MASK_LENGTH_CHOICES,
|
||||
label='Mask length'
|
||||
label='Mask length',
|
||||
widget=StaticSelect2()
|
||||
)
|
||||
vrf = FilterChoiceField(
|
||||
queryset=VRF.objects.annotate(
|
||||
filter_count=Count('ip_addresses')
|
||||
),
|
||||
queryset=VRF.objects.all(),
|
||||
to_field_name='rd',
|
||||
label='VRF',
|
||||
null_label='-- Global --'
|
||||
null_label='-- Global --',
|
||||
widget=APISelectMultiple(
|
||||
api_url="/api/ipam/vrfs/",
|
||||
value_field="slug",
|
||||
null_option=True,
|
||||
)
|
||||
)
|
||||
tenant = FilterChoiceField(
|
||||
queryset=Tenant.objects.annotate(
|
||||
filter_count=Count('ip_addresses')
|
||||
),
|
||||
queryset=Tenant.objects.all(),
|
||||
to_field_name='slug',
|
||||
null_label='-- None --'
|
||||
null_label='-- None --',
|
||||
widget=APISelectMultiple(
|
||||
api_url="/api/tenancy/tenants/",
|
||||
value_field="slug",
|
||||
null_option=True,
|
||||
)
|
||||
)
|
||||
status = AnnotatedMultipleChoiceField(
|
||||
status = forms.MultipleChoiceField(
|
||||
choices=IPADDRESS_STATUS_CHOICES,
|
||||
annotate=IPAddress.objects.all(),
|
||||
annotate_field='status',
|
||||
required=False
|
||||
required=False,
|
||||
widget=StaticSelect2Multiple()
|
||||
)
|
||||
role = AnnotatedMultipleChoiceField(
|
||||
role = forms.MultipleChoiceField(
|
||||
choices=IPADDRESS_ROLE_CHOICES,
|
||||
annotate=IPAddress.objects.all(),
|
||||
annotate_field='role',
|
||||
required=False
|
||||
required=False,
|
||||
widget=StaticSelect2Multiple()
|
||||
)
|
||||
|
||||
|
||||
@ -929,6 +1011,11 @@ class VLANGroupForm(BootstrapMixin, forms.ModelForm):
|
||||
fields = [
|
||||
'site', 'name', 'slug',
|
||||
]
|
||||
widgets = {
|
||||
'site': APISelect(
|
||||
api_url="/api/dcim/sites/"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
class VLANGroupCSVForm(forms.ModelForm):
|
||||
@ -953,11 +1040,14 @@ class VLANGroupCSVForm(forms.ModelForm):
|
||||
|
||||
class VLANGroupFilterForm(BootstrapMixin, forms.Form):
|
||||
site = FilterChoiceField(
|
||||
queryset=Site.objects.annotate(
|
||||
filter_count=Count('vlan_groups')
|
||||
),
|
||||
queryset=Site.objects.all(),
|
||||
to_field_name='slug',
|
||||
null_label='-- Global --'
|
||||
null_label='-- Global --',
|
||||
widget=APISelectMultiple(
|
||||
api_url="/api/dcim/sites/",
|
||||
value_field="slug",
|
||||
null_option=True,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@ -969,9 +1059,12 @@ class VLANForm(BootstrapMixin, TenancyForm, CustomFieldForm):
|
||||
site = forms.ModelChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
required=False,
|
||||
widget=forms.Select(
|
||||
widget=APISelect(
|
||||
api_url="/api/dcim/sites/",
|
||||
filter_for={
|
||||
'group': 'site_id'
|
||||
},
|
||||
attrs={
|
||||
'filter-for': 'group',
|
||||
'nullable': 'true',
|
||||
}
|
||||
)
|
||||
@ -984,7 +1077,7 @@ class VLANForm(BootstrapMixin, TenancyForm, CustomFieldForm):
|
||||
required=False,
|
||||
label='Group',
|
||||
widget=APISelect(
|
||||
api_url='/api/ipam/vlan-groups/?site_id={{site}}',
|
||||
api_url='/api/ipam/vlan-groups/',
|
||||
)
|
||||
)
|
||||
tags = TagField(required=False)
|
||||
@ -1002,6 +1095,12 @@ class VLANForm(BootstrapMixin, TenancyForm, CustomFieldForm):
|
||||
'status': "Operational status of this VLAN",
|
||||
'role': "The primary function of this VLAN",
|
||||
}
|
||||
widgets = {
|
||||
'status': StaticSelect2(),
|
||||
'role': APISelect(
|
||||
api_url="/api/ipam/roles/"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
class VLANCSVForm(forms.ModelForm):
|
||||
@ -1077,23 +1176,36 @@ class VLANBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditFor
|
||||
)
|
||||
site = forms.ModelChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
required=False
|
||||
required=False,
|
||||
widget=APISelect(
|
||||
api_url="/api/dcim/sites/"
|
||||
)
|
||||
)
|
||||
group = forms.ModelChoiceField(
|
||||
queryset=VLANGroup.objects.all(),
|
||||
required=False
|
||||
required=False,
|
||||
widget=APISelect(
|
||||
api_url="/api/ipam/vlan-groups/"
|
||||
)
|
||||
)
|
||||
tenant = forms.ModelChoiceField(
|
||||
queryset=Tenant.objects.all(),
|
||||
required=False
|
||||
required=False,
|
||||
widget=APISelect(
|
||||
api_url="/api/tenancy/tenants/"
|
||||
)
|
||||
)
|
||||
status = forms.ChoiceField(
|
||||
choices=add_blank_choice(VLAN_STATUS_CHOICES),
|
||||
required=False
|
||||
required=False,
|
||||
widget=StaticSelect2()
|
||||
)
|
||||
role = forms.ModelChoiceField(
|
||||
queryset=Role.objects.all(),
|
||||
required=False
|
||||
required=False,
|
||||
widget=APISelect(
|
||||
api_url="/api/ipam/roles/"
|
||||
)
|
||||
)
|
||||
description = forms.CharField(
|
||||
max_length=100,
|
||||
@ -1113,38 +1225,48 @@ class VLANFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
||||
label='Search'
|
||||
)
|
||||
site = FilterChoiceField(
|
||||
queryset=Site.objects.annotate(
|
||||
filter_count=Count('vlans')
|
||||
),
|
||||
queryset=Site.objects.all(),
|
||||
to_field_name='slug',
|
||||
null_label='-- Global --'
|
||||
null_label='-- Global --',
|
||||
widget=APISelectMultiple(
|
||||
api_url="/api/dcim/sites/",
|
||||
value_field="slug",
|
||||
null_option=True,
|
||||
)
|
||||
)
|
||||
group_id = FilterChoiceField(
|
||||
queryset=VLANGroup.objects.annotate(
|
||||
filter_count=Count('vlans')
|
||||
),
|
||||
queryset=VLANGroup.objects.all(),
|
||||
label='VLAN group',
|
||||
null_label='-- None --'
|
||||
null_label='-- None --',
|
||||
widget=APISelectMultiple(
|
||||
api_url="/api/ipam/vlan-groups/",
|
||||
null_option=True,
|
||||
)
|
||||
)
|
||||
tenant = FilterChoiceField(
|
||||
queryset=Tenant.objects.annotate(
|
||||
filter_count=Count('vlans')
|
||||
),
|
||||
queryset=Tenant.objects.all(),
|
||||
to_field_name='slug',
|
||||
null_label='-- None --'
|
||||
null_label='-- None --',
|
||||
widget=APISelectMultiple(
|
||||
api_url="/api/tenancy/tenants/",
|
||||
value_field="slug",
|
||||
null_option=True,
|
||||
)
|
||||
)
|
||||
status = AnnotatedMultipleChoiceField(
|
||||
status = forms.MultipleChoiceField(
|
||||
choices=VLAN_STATUS_CHOICES,
|
||||
annotate=VLAN.objects.all(),
|
||||
annotate_field='status',
|
||||
required=False
|
||||
required=False,
|
||||
widget=StaticSelect2Multiple()
|
||||
)
|
||||
role = FilterChoiceField(
|
||||
queryset=Role.objects.annotate(
|
||||
filter_count=Count('vlans')
|
||||
),
|
||||
queryset=Role.objects.all(),
|
||||
to_field_name='slug',
|
||||
null_label='-- None --'
|
||||
null_label='-- None --',
|
||||
widget=APISelectMultiple(
|
||||
api_url="/api/ipam/roles/",
|
||||
value_field="slug",
|
||||
null_option=True,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@ -1166,6 +1288,10 @@ class ServiceForm(BootstrapMixin, CustomFieldForm):
|
||||
'ipaddresses': "IP address assignment is optional. If no IPs are selected, the service is assumed to be "
|
||||
"reachable via all IPs assigned to the device.",
|
||||
}
|
||||
widgets = {
|
||||
'protocol': StaticSelect2(),
|
||||
'ipaddresses': StaticSelect2Multiple(),
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
@ -1192,10 +1318,11 @@ class ServiceFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
||||
)
|
||||
protocol = forms.ChoiceField(
|
||||
choices=add_blank_choice(IP_PROTOCOL_CHOICES),
|
||||
required=False
|
||||
required=False,
|
||||
widget=StaticSelect2Multiple()
|
||||
)
|
||||
port = forms.IntegerField(
|
||||
required=False
|
||||
required=False,
|
||||
)
|
||||
|
||||
|
||||
@ -1206,7 +1333,8 @@ class ServiceBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
|
||||
)
|
||||
protocol = forms.ChoiceField(
|
||||
choices=add_blank_choice(IP_PROTOCOL_CHOICES),
|
||||
required=False
|
||||
required=False,
|
||||
widget=StaticSelect2()
|
||||
)
|
||||
port = forms.IntegerField(
|
||||
validators=[
|
||||
@ -1222,5 +1350,5 @@ class ServiceBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
|
||||
|
||||
class Meta:
|
||||
nullable_fields = [
|
||||
'site', 'group', 'tenant', 'role', 'description',
|
||||
'site', 'tenant', 'role', 'description',
|
||||
]
|
||||
|
Reference in New Issue
Block a user