Sfoglia il codice sorgente

Move null_option to DynamicModelChoiceMixin

Jeremy Stretch 5 anni fa
parent
commit
8a8b4e728a

+ 11 - 29
netbox/dcim/forms.py

@@ -672,9 +672,7 @@ class RackFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
         ),
         required=False,
         label='Rack group',
-        widget=APISelectMultiple(
-            null_option=True
-        )
+        null_option='None'
     )
     status = forms.MultipleChoiceField(
         choices=RackStatusChoices,
@@ -685,9 +683,7 @@ class RackFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
         queryset=RackRole.objects.all(),
         to_field_name='slug',
         required=False,
-        widget=APISelectMultiple(
-            null_option=True,
-        )
+        null_option='None'
     )
     tag = TagFilterField(model)
 
@@ -853,9 +849,7 @@ class RackReservationFilterForm(BootstrapMixin, TenancyFilterForm):
         queryset=RackGroup.objects.prefetch_related('site'),
         required=False,
         label='Rack group',
-        widget=APISelectMultiple(
-            null_option=True,
-        )
+        null_option='None'
     )
     tag = TagFilterField(model)
 
@@ -2124,9 +2118,7 @@ class DeviceFilterForm(BootstrapMixin, LocalConfigContextFilterForm, TenancyFilt
         queryset=Rack.objects.all(),
         required=False,
         label='Rack',
-        widget=APISelectMultiple(
-            null_option=True,
-        )
+        null_option='None'
     )
     role = DynamicModelMultipleChoiceField(
         queryset=DeviceRole.objects.all(),
@@ -2155,9 +2147,7 @@ class DeviceFilterForm(BootstrapMixin, LocalConfigContextFilterForm, TenancyFilt
         queryset=Platform.objects.all(),
         to_field_name='slug',
         required=False,
-        widget=APISelectMultiple(
-            null_option=True,
-        )
+        null_option='None'
     )
     status = forms.MultipleChoiceField(
         choices=DeviceStatusChoices,
@@ -3879,8 +3869,8 @@ class CableFilterForm(BootstrapMixin, forms.Form):
         queryset=Rack.objects.all(),
         required=False,
         label='Rack',
+        null_option='None',
         widget=APISelectMultiple(
-            null_option=True,
             filter_for={
                 'device_id': 'rack_id',
             }
@@ -4208,8 +4198,8 @@ class VirtualChassisFilterForm(BootstrapMixin, CustomFieldFilterForm):
         queryset=TenantGroup.objects.all(),
         to_field_name='slug',
         required=False,
+        null_option='None',
         widget=APISelectMultiple(
-            null_option=True,
             filter_for={
                 'tenant': 'group'
             }
@@ -4219,9 +4209,7 @@ class VirtualChassisFilterForm(BootstrapMixin, CustomFieldFilterForm):
         queryset=Tenant.objects.all(),
         to_field_name='slug',
         required=False,
-        widget=APISelectMultiple(
-            null_option=True,
-        )
+        null_option='None'
     )
     tag = TagFilterField(model)
 
@@ -4336,9 +4324,7 @@ class PowerPanelFilterForm(BootstrapMixin, CustomFieldFilterForm):
         queryset=RackGroup.objects.all(),
         required=False,
         label='Rack group (ID)',
-        widget=APISelectMultiple(
-            null_option=True,
-        )
+        null_option='None'
     )
     tag = TagFilterField(model)
 
@@ -4555,17 +4541,13 @@ class PowerFeedFilterForm(BootstrapMixin, CustomFieldFilterForm):
         queryset=PowerPanel.objects.all(),
         required=False,
         label='Power panel',
-        widget=APISelectMultiple(
-            null_option=True,
-        )
+        null_option='None'
     )
     rack_id = DynamicModelMultipleChoiceField(
         queryset=Rack.objects.all(),
         required=False,
         label='Rack',
-        widget=APISelectMultiple(
-            null_option=True,
-        )
+        null_option='None'
     )
     status = forms.MultipleChoiceField(
         choices=PowerFeedStatusChoices,

+ 8 - 24
netbox/ipam/forms.py

@@ -464,9 +464,7 @@ class PrefixFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm)
         queryset=VRF.objects.all(),
         required=False,
         label='VRF',
-        widget=APISelectMultiple(
-            null_option=True,
-        )
+        null_option='Global'
     )
     status = forms.MultipleChoiceField(
         choices=PrefixStatusChoices,
@@ -487,17 +485,13 @@ class PrefixFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm)
         queryset=Site.objects.all(),
         to_field_name='slug',
         required=False,
-        widget=APISelectMultiple(
-            null_option=True,
-        )
+        null_option='None'
     )
     role = DynamicModelMultipleChoiceField(
         queryset=Role.objects.all(),
         to_field_name='slug',
         required=False,
-        widget=APISelectMultiple(
-            null_option=True,
-        )
+        null_option='None'
     )
     is_pool = forms.NullBooleanField(
         required=False,
@@ -910,9 +904,7 @@ class IPAddressFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterFo
         queryset=VRF.objects.all(),
         required=False,
         label='VRF',
-        widget=APISelectMultiple(
-            null_option=True,
-        )
+        null_option='Global'
     )
     status = forms.MultipleChoiceField(
         choices=IPAddressStatusChoices,
@@ -981,9 +973,7 @@ class VLANGroupFilterForm(BootstrapMixin, forms.Form):
         queryset=Site.objects.all(),
         to_field_name='slug',
         required=False,
-        widget=APISelectMultiple(
-            null_option=True,
-        )
+        null_option='None'
     )
 
 
@@ -1147,17 +1137,13 @@ class VLANFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
         queryset=Site.objects.all(),
         to_field_name='slug',
         required=False,
-        widget=APISelectMultiple(
-            null_option=True,
-        )
+        null_option='None'
     )
     group_id = DynamicModelMultipleChoiceField(
         queryset=VLANGroup.objects.all(),
         required=False,
         label='VLAN group',
-        widget=APISelectMultiple(
-            null_option=True,
-        )
+        null_option='None'
     )
     status = forms.MultipleChoiceField(
         choices=VLANStatusChoices,
@@ -1168,9 +1154,7 @@ class VLANFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
         queryset=Role.objects.all(),
         to_field_name='slug',
         required=False,
-        widget=APISelectMultiple(
-            null_option=True,
-        )
+        null_option='None'
     )
     tag = TagFilterField(model)
 

+ 1 - 1
netbox/project-static/js/forms.js

@@ -247,7 +247,7 @@ $(document).ready(function() {
                 if (element.getAttribute('data-null-option') && data.previous === null) {
                     results.unshift({
                         id: 'null',
-                        text: 'None'
+                        text: element.getAttribute('data-null-option')
                     });
                 }
 

+ 3 - 7
netbox/tenancy/forms.py

@@ -106,9 +106,7 @@ class TenantFilterForm(BootstrapMixin, CustomFieldFilterForm):
         queryset=TenantGroup.objects.all(),
         to_field_name='slug',
         required=False,
-        widget=APISelectMultiple(
-            null_option=True,
-        )
+        null_option='None'
     )
     tag = TagFilterField(model)
 
@@ -152,8 +150,8 @@ class TenancyFilterForm(forms.Form):
         queryset=TenantGroup.objects.all(),
         to_field_name='slug',
         required=False,
+        null_option='None',
         widget=APISelectMultiple(
-            null_option=True,
             filter_for={
                 'tenant': 'group'
             }
@@ -163,7 +161,5 @@ class TenancyFilterForm(forms.Form):
         queryset=Tenant.objects.all(),
         to_field_name='slug',
         required=False,
-        widget=APISelectMultiple(
-            null_option=True,
-        )
+        null_option='None'
     )

+ 11 - 1
netbox/utilities/forms/fields.py

@@ -245,12 +245,18 @@ class TagFilterField(forms.MultipleChoiceField):
 
 
 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
     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.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
         # by widget_attrs()
@@ -267,6 +273,10 @@ class DynamicModelChoiceMixin:
         if 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
         for key, value in self.query_params.items():
             widget.add_additional_query_param(key, value)

+ 0 - 4
netbox/utilities/forms/widgets.py

@@ -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.
     :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.
-    :param null_option: If true, include the static null option in the selection list.
     """
     def __init__(
         self,
@@ -155,7 +154,6 @@ class APISelect(SelectWithDisabled):
         disabled_indicator=None,
         filter_for=None,
         additional_query_params=None,
-        null_option=False,
         full=False,
         *args,
         **kwargs
@@ -178,8 +176,6 @@ class APISelect(SelectWithDisabled):
         if additional_query_params:
             for key, value in additional_query_params.items():
                 self.add_additional_query_param(key, value)
-        if null_option:
-            self.attrs['data-null-option'] = 1
 
     def add_filter_for(self, name, value):
         """

+ 8 - 20
netbox/virtualization/forms.py

@@ -182,17 +182,13 @@ class ClusterFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm
         queryset=Site.objects.all(),
         to_field_name='slug',
         required=False,
-        widget=APISelectMultiple(
-            null_option=True,
-        )
+        null_option='None'
     )
     group = DynamicModelMultipleChoiceField(
         queryset=ClusterGroup.objects.all(),
         to_field_name='slug',
         required=False,
-        widget=APISelectMultiple(
-            null_option=True,
-        )
+        null_option='None'
     )
     tag = TagFilterField(model)
 
@@ -485,17 +481,13 @@ class VirtualMachineFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFil
         queryset=ClusterGroup.objects.all(),
         to_field_name='slug',
         required=False,
-        widget=APISelectMultiple(
-            null_option=True,
-        )
+        null_option='None'
     )
     cluster_type = DynamicModelMultipleChoiceField(
         queryset=ClusterType.objects.all(),
         to_field_name='slug',
         required=False,
-        widget=APISelectMultiple(
-            null_option=True,
-        )
+        null_option='None'
     )
     cluster_id = DynamicModelMultipleChoiceField(
         queryset=Cluster.objects.all(),
@@ -516,18 +508,16 @@ class VirtualMachineFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFil
         queryset=Site.objects.all(),
         to_field_name='slug',
         required=False,
-        widget=APISelectMultiple(
-            null_option=True,
-        )
+        null_option='None'
     )
     role = DynamicModelMultipleChoiceField(
         queryset=DeviceRole.objects.filter(vm_role=True),
         to_field_name='slug',
         required=False,
+        null_option='None',
         query_params={
             'vm_role': "True"
-        },
-        widget=APISelectMultiple(null_option=True)
+        }
     )
     status = forms.MultipleChoiceField(
         choices=VirtualMachineStatusChoices,
@@ -538,9 +528,7 @@ class VirtualMachineFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFil
         queryset=Platform.objects.all(),
         to_field_name='slug',
         required=False,
-        widget=APISelectMultiple(
-            null_option=True,
-        )
+        null_option='None'
     )
     mac_address = forms.CharField(
         required=False,