mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Move null_option to DynamicModelChoiceMixin
This commit is contained in:
@ -672,9 +672,7 @@ class RackFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
|
|||||||
),
|
),
|
||||||
required=False,
|
required=False,
|
||||||
label='Rack group',
|
label='Rack group',
|
||||||
widget=APISelectMultiple(
|
null_option='None'
|
||||||
null_option=True
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
status = forms.MultipleChoiceField(
|
status = forms.MultipleChoiceField(
|
||||||
choices=RackStatusChoices,
|
choices=RackStatusChoices,
|
||||||
@ -685,9 +683,7 @@ class RackFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
|
|||||||
queryset=RackRole.objects.all(),
|
queryset=RackRole.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
required=False,
|
required=False,
|
||||||
widget=APISelectMultiple(
|
null_option='None'
|
||||||
null_option=True,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
tag = TagFilterField(model)
|
tag = TagFilterField(model)
|
||||||
|
|
||||||
@ -853,9 +849,7 @@ class RackReservationFilterForm(BootstrapMixin, TenancyFilterForm):
|
|||||||
queryset=RackGroup.objects.prefetch_related('site'),
|
queryset=RackGroup.objects.prefetch_related('site'),
|
||||||
required=False,
|
required=False,
|
||||||
label='Rack group',
|
label='Rack group',
|
||||||
widget=APISelectMultiple(
|
null_option='None'
|
||||||
null_option=True,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
tag = TagFilterField(model)
|
tag = TagFilterField(model)
|
||||||
|
|
||||||
@ -2124,9 +2118,7 @@ class DeviceFilterForm(BootstrapMixin, LocalConfigContextFilterForm, TenancyFilt
|
|||||||
queryset=Rack.objects.all(),
|
queryset=Rack.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
label='Rack',
|
label='Rack',
|
||||||
widget=APISelectMultiple(
|
null_option='None'
|
||||||
null_option=True,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
role = DynamicModelMultipleChoiceField(
|
role = DynamicModelMultipleChoiceField(
|
||||||
queryset=DeviceRole.objects.all(),
|
queryset=DeviceRole.objects.all(),
|
||||||
@ -2155,9 +2147,7 @@ class DeviceFilterForm(BootstrapMixin, LocalConfigContextFilterForm, TenancyFilt
|
|||||||
queryset=Platform.objects.all(),
|
queryset=Platform.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
required=False,
|
required=False,
|
||||||
widget=APISelectMultiple(
|
null_option='None'
|
||||||
null_option=True,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
status = forms.MultipleChoiceField(
|
status = forms.MultipleChoiceField(
|
||||||
choices=DeviceStatusChoices,
|
choices=DeviceStatusChoices,
|
||||||
@ -3879,8 +3869,8 @@ class CableFilterForm(BootstrapMixin, forms.Form):
|
|||||||
queryset=Rack.objects.all(),
|
queryset=Rack.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
label='Rack',
|
label='Rack',
|
||||||
|
null_option='None',
|
||||||
widget=APISelectMultiple(
|
widget=APISelectMultiple(
|
||||||
null_option=True,
|
|
||||||
filter_for={
|
filter_for={
|
||||||
'device_id': 'rack_id',
|
'device_id': 'rack_id',
|
||||||
}
|
}
|
||||||
@ -4208,8 +4198,8 @@ class VirtualChassisFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
queryset=TenantGroup.objects.all(),
|
queryset=TenantGroup.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
required=False,
|
required=False,
|
||||||
|
null_option='None',
|
||||||
widget=APISelectMultiple(
|
widget=APISelectMultiple(
|
||||||
null_option=True,
|
|
||||||
filter_for={
|
filter_for={
|
||||||
'tenant': 'group'
|
'tenant': 'group'
|
||||||
}
|
}
|
||||||
@ -4219,9 +4209,7 @@ class VirtualChassisFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
queryset=Tenant.objects.all(),
|
queryset=Tenant.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
required=False,
|
required=False,
|
||||||
widget=APISelectMultiple(
|
null_option='None'
|
||||||
null_option=True,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
tag = TagFilterField(model)
|
tag = TagFilterField(model)
|
||||||
|
|
||||||
@ -4336,9 +4324,7 @@ class PowerPanelFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
queryset=RackGroup.objects.all(),
|
queryset=RackGroup.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
label='Rack group (ID)',
|
label='Rack group (ID)',
|
||||||
widget=APISelectMultiple(
|
null_option='None'
|
||||||
null_option=True,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
tag = TagFilterField(model)
|
tag = TagFilterField(model)
|
||||||
|
|
||||||
@ -4555,17 +4541,13 @@ class PowerFeedFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
queryset=PowerPanel.objects.all(),
|
queryset=PowerPanel.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
label='Power panel',
|
label='Power panel',
|
||||||
widget=APISelectMultiple(
|
null_option='None'
|
||||||
null_option=True,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
rack_id = DynamicModelMultipleChoiceField(
|
rack_id = DynamicModelMultipleChoiceField(
|
||||||
queryset=Rack.objects.all(),
|
queryset=Rack.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
label='Rack',
|
label='Rack',
|
||||||
widget=APISelectMultiple(
|
null_option='None'
|
||||||
null_option=True,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
status = forms.MultipleChoiceField(
|
status = forms.MultipleChoiceField(
|
||||||
choices=PowerFeedStatusChoices,
|
choices=PowerFeedStatusChoices,
|
||||||
|
@ -464,9 +464,7 @@ class PrefixFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm)
|
|||||||
queryset=VRF.objects.all(),
|
queryset=VRF.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
label='VRF',
|
label='VRF',
|
||||||
widget=APISelectMultiple(
|
null_option='Global'
|
||||||
null_option=True,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
status = forms.MultipleChoiceField(
|
status = forms.MultipleChoiceField(
|
||||||
choices=PrefixStatusChoices,
|
choices=PrefixStatusChoices,
|
||||||
@ -487,17 +485,13 @@ class PrefixFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm)
|
|||||||
queryset=Site.objects.all(),
|
queryset=Site.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
required=False,
|
required=False,
|
||||||
widget=APISelectMultiple(
|
null_option='None'
|
||||||
null_option=True,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
role = DynamicModelMultipleChoiceField(
|
role = DynamicModelMultipleChoiceField(
|
||||||
queryset=Role.objects.all(),
|
queryset=Role.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
required=False,
|
required=False,
|
||||||
widget=APISelectMultiple(
|
null_option='None'
|
||||||
null_option=True,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
is_pool = forms.NullBooleanField(
|
is_pool = forms.NullBooleanField(
|
||||||
required=False,
|
required=False,
|
||||||
@ -910,9 +904,7 @@ class IPAddressFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterFo
|
|||||||
queryset=VRF.objects.all(),
|
queryset=VRF.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
label='VRF',
|
label='VRF',
|
||||||
widget=APISelectMultiple(
|
null_option='Global'
|
||||||
null_option=True,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
status = forms.MultipleChoiceField(
|
status = forms.MultipleChoiceField(
|
||||||
choices=IPAddressStatusChoices,
|
choices=IPAddressStatusChoices,
|
||||||
@ -981,9 +973,7 @@ class VLANGroupFilterForm(BootstrapMixin, forms.Form):
|
|||||||
queryset=Site.objects.all(),
|
queryset=Site.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
required=False,
|
required=False,
|
||||||
widget=APISelectMultiple(
|
null_option='None'
|
||||||
null_option=True,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -1147,17 +1137,13 @@ class VLANFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
|
|||||||
queryset=Site.objects.all(),
|
queryset=Site.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
required=False,
|
required=False,
|
||||||
widget=APISelectMultiple(
|
null_option='None'
|
||||||
null_option=True,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
group_id = DynamicModelMultipleChoiceField(
|
group_id = DynamicModelMultipleChoiceField(
|
||||||
queryset=VLANGroup.objects.all(),
|
queryset=VLANGroup.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
label='VLAN group',
|
label='VLAN group',
|
||||||
widget=APISelectMultiple(
|
null_option='None'
|
||||||
null_option=True,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
status = forms.MultipleChoiceField(
|
status = forms.MultipleChoiceField(
|
||||||
choices=VLANStatusChoices,
|
choices=VLANStatusChoices,
|
||||||
@ -1168,9 +1154,7 @@ class VLANFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
|
|||||||
queryset=Role.objects.all(),
|
queryset=Role.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
required=False,
|
required=False,
|
||||||
widget=APISelectMultiple(
|
null_option='None'
|
||||||
null_option=True,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
tag = TagFilterField(model)
|
tag = TagFilterField(model)
|
||||||
|
|
||||||
|
@ -247,7 +247,7 @@ $(document).ready(function() {
|
|||||||
if (element.getAttribute('data-null-option') && data.previous === null) {
|
if (element.getAttribute('data-null-option') && data.previous === null) {
|
||||||
results.unshift({
|
results.unshift({
|
||||||
id: 'null',
|
id: 'null',
|
||||||
text: 'None'
|
text: element.getAttribute('data-null-option')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,9 +106,7 @@ class TenantFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
queryset=TenantGroup.objects.all(),
|
queryset=TenantGroup.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
required=False,
|
required=False,
|
||||||
widget=APISelectMultiple(
|
null_option='None'
|
||||||
null_option=True,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
tag = TagFilterField(model)
|
tag = TagFilterField(model)
|
||||||
|
|
||||||
@ -152,8 +150,8 @@ class TenancyFilterForm(forms.Form):
|
|||||||
queryset=TenantGroup.objects.all(),
|
queryset=TenantGroup.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
required=False,
|
required=False,
|
||||||
|
null_option='None',
|
||||||
widget=APISelectMultiple(
|
widget=APISelectMultiple(
|
||||||
null_option=True,
|
|
||||||
filter_for={
|
filter_for={
|
||||||
'tenant': 'group'
|
'tenant': 'group'
|
||||||
}
|
}
|
||||||
@ -163,7 +161,5 @@ class TenancyFilterForm(forms.Form):
|
|||||||
queryset=Tenant.objects.all(),
|
queryset=Tenant.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
required=False,
|
required=False,
|
||||||
widget=APISelectMultiple(
|
null_option='None'
|
||||||
null_option=True,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
@ -245,12 +245,18 @@ class TagFilterField(forms.MultipleChoiceField):
|
|||||||
|
|
||||||
|
|
||||||
class DynamicModelChoiceMixin:
|
class DynamicModelChoiceMixin:
|
||||||
|
"""
|
||||||
|
:param display_field: The name of the attribute of an API response object to display in the selection list
|
||||||
|
:param query_params: A dictionary of additional key/value pairs to attach to the API request
|
||||||
|
:param null_option: The string used to represent a null selection (if any)
|
||||||
|
"""
|
||||||
filter = django_filters.ModelChoiceFilter
|
filter = django_filters.ModelChoiceFilter
|
||||||
widget = widgets.APISelect
|
widget = widgets.APISelect
|
||||||
|
|
||||||
def __init__(self, *args, display_field='name', query_params=None, **kwargs):
|
def __init__(self, *args, display_field='name', query_params=None, null_option=None, **kwargs):
|
||||||
self.display_field = display_field
|
self.display_field = display_field
|
||||||
self.query_params = query_params or {}
|
self.query_params = query_params or {}
|
||||||
|
self.null_option = null_option
|
||||||
|
|
||||||
# to_field_name is set by ModelChoiceField.__init__(), but we need to set it early for reference
|
# to_field_name is set by ModelChoiceField.__init__(), but we need to set it early for reference
|
||||||
# by widget_attrs()
|
# by widget_attrs()
|
||||||
@ -267,6 +273,10 @@ class DynamicModelChoiceMixin:
|
|||||||
if self.to_field_name:
|
if self.to_field_name:
|
||||||
attrs['value-field'] = self.to_field_name
|
attrs['value-field'] = self.to_field_name
|
||||||
|
|
||||||
|
# Set the string used to represent a null option
|
||||||
|
if self.null_option is not None:
|
||||||
|
attrs['data-null-option'] = self.null_option
|
||||||
|
|
||||||
# Attach any static query parameters
|
# Attach any static query parameters
|
||||||
for key, value in self.query_params.items():
|
for key, value in self.query_params.items():
|
||||||
widget.add_additional_query_param(key, value)
|
widget.add_additional_query_param(key, value)
|
||||||
|
@ -146,7 +146,6 @@ class APISelect(SelectWithDisabled):
|
|||||||
name of the filter-for field (child field) and the value is the name of the query param filter.
|
name of the filter-for field (child field) and the value is the name of the query param filter.
|
||||||
:param additional_query_params: Optional) A dict of query params to append to the API request. The key is the
|
:param additional_query_params: Optional) A dict of query params to append to the API request. The key is the
|
||||||
name of the query param and the value if the query param's value.
|
name of the query param and the value if the query param's value.
|
||||||
:param null_option: If true, include the static null option in the selection list.
|
|
||||||
"""
|
"""
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@ -155,7 +154,6 @@ class APISelect(SelectWithDisabled):
|
|||||||
disabled_indicator=None,
|
disabled_indicator=None,
|
||||||
filter_for=None,
|
filter_for=None,
|
||||||
additional_query_params=None,
|
additional_query_params=None,
|
||||||
null_option=False,
|
|
||||||
full=False,
|
full=False,
|
||||||
*args,
|
*args,
|
||||||
**kwargs
|
**kwargs
|
||||||
@ -178,8 +176,6 @@ class APISelect(SelectWithDisabled):
|
|||||||
if additional_query_params:
|
if additional_query_params:
|
||||||
for key, value in additional_query_params.items():
|
for key, value in additional_query_params.items():
|
||||||
self.add_additional_query_param(key, value)
|
self.add_additional_query_param(key, value)
|
||||||
if null_option:
|
|
||||||
self.attrs['data-null-option'] = 1
|
|
||||||
|
|
||||||
def add_filter_for(self, name, value):
|
def add_filter_for(self, name, value):
|
||||||
"""
|
"""
|
||||||
|
@ -182,17 +182,13 @@ class ClusterFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm
|
|||||||
queryset=Site.objects.all(),
|
queryset=Site.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
required=False,
|
required=False,
|
||||||
widget=APISelectMultiple(
|
null_option='None'
|
||||||
null_option=True,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
group = DynamicModelMultipleChoiceField(
|
group = DynamicModelMultipleChoiceField(
|
||||||
queryset=ClusterGroup.objects.all(),
|
queryset=ClusterGroup.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
required=False,
|
required=False,
|
||||||
widget=APISelectMultiple(
|
null_option='None'
|
||||||
null_option=True,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
tag = TagFilterField(model)
|
tag = TagFilterField(model)
|
||||||
|
|
||||||
@ -485,17 +481,13 @@ class VirtualMachineFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFil
|
|||||||
queryset=ClusterGroup.objects.all(),
|
queryset=ClusterGroup.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
required=False,
|
required=False,
|
||||||
widget=APISelectMultiple(
|
null_option='None'
|
||||||
null_option=True,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
cluster_type = DynamicModelMultipleChoiceField(
|
cluster_type = DynamicModelMultipleChoiceField(
|
||||||
queryset=ClusterType.objects.all(),
|
queryset=ClusterType.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
required=False,
|
required=False,
|
||||||
widget=APISelectMultiple(
|
null_option='None'
|
||||||
null_option=True,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
cluster_id = DynamicModelMultipleChoiceField(
|
cluster_id = DynamicModelMultipleChoiceField(
|
||||||
queryset=Cluster.objects.all(),
|
queryset=Cluster.objects.all(),
|
||||||
@ -516,18 +508,16 @@ class VirtualMachineFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFil
|
|||||||
queryset=Site.objects.all(),
|
queryset=Site.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
required=False,
|
required=False,
|
||||||
widget=APISelectMultiple(
|
null_option='None'
|
||||||
null_option=True,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
role = DynamicModelMultipleChoiceField(
|
role = DynamicModelMultipleChoiceField(
|
||||||
queryset=DeviceRole.objects.filter(vm_role=True),
|
queryset=DeviceRole.objects.filter(vm_role=True),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
required=False,
|
required=False,
|
||||||
|
null_option='None',
|
||||||
query_params={
|
query_params={
|
||||||
'vm_role': "True"
|
'vm_role': "True"
|
||||||
},
|
}
|
||||||
widget=APISelectMultiple(null_option=True)
|
|
||||||
)
|
)
|
||||||
status = forms.MultipleChoiceField(
|
status = forms.MultipleChoiceField(
|
||||||
choices=VirtualMachineStatusChoices,
|
choices=VirtualMachineStatusChoices,
|
||||||
@ -538,9 +528,7 @@ class VirtualMachineFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFil
|
|||||||
queryset=Platform.objects.all(),
|
queryset=Platform.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
required=False,
|
required=False,
|
||||||
widget=APISelectMultiple(
|
null_option='None'
|
||||||
null_option=True,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
mac_address = forms.CharField(
|
mac_address = forms.CharField(
|
||||||
required=False,
|
required=False,
|
||||||
|
Reference in New Issue
Block a user